library(readr)
library(tidyverse)
library(forcats)
library(plotly)
library(knitr, warn.conflicts = FALSE, quietly=TRUE)
library(RColorBrewer)
library(stringr)
library(dygraphs)
library(xts)
myPalette <- brewer.pal(10, "Paired")
vgsales <- read_csv("vgsales.csv")
Rows: 16598 Columns: 11
-- Column specification -------------------------------------------------------------------------------------
Delimiter: ","
chr (5): Name, Platform, Year, Genre, Publisher
dbl (6): Rank, NA_Sales, EU_Sales, JP_Sales, Other_Sales, Global_Sales

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.

Das verwendete Dataset des Projekts: https://www.kaggle.com/datasets/gregorut/videogamesales

Dieses Dataset umfasst verschiedene Daten zu Videogamereleases und Sales zwischen 1980 und 2016.

Ideen/Statements:

Bestimmte Entwickler/Publisher häufen sich (Nintendo/EA) Ältere Plattformen/spiele haben mehr verkäufe bzw Wie hat sich die Anzahl der verkäufe im laufe der jahre entwickelt? Genrenentwicklung über die Jahre Welche Spiele/Publisher/Genres in welchen Teilen der welt sich häufen (Nintendo in Asien, Shooter in US/EU) Gibt es Statistische zusammenhänge zwischen einzelnen Faktoren e.g. Genre -> Sales Welche Jahre sind die besten in der Anzahl der releasten games und hängt dies mit den Sales zusammen? (je mehr Total Sales desto mehr Games verkaufen sich) Welche Jahre sind die besten in Anzahl Sales pro game (neuer = besser?) Welche Plattform ist die beste und unterscheidet sich diese nach Region? Gibt es Unterschiede in den Regionen/hängt das mit der Anzahl der Einwohner der Region zusammen? (Asia>US>EU)

Zuerst schauen wir und die Anzahl der Videospiele und die Anzahl der Verkäufe im laufe der Jahre an.

Hierzu verwenden wir Liniendiagramme. Außerdem filtern wir alle Datensätze in denen kein Jahr angegeben ist sowie Datensätze mit den Jahren 2017 und 2020 um Fehlerhafte Daten und unvollständige Daten aus der Liste zu entfernen.

Game Releases over the Years

Game Amount


grouped <- vgsales  %>%                                 
  group_by(Year) %>%
  dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Anzahl)

ax <- list(
  title = "Year"
)

ay <- list(
  title = "Amount"

)

filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'lines', fill = 'tozeroy' ,colors = myPalette) %>% 
  layout(title="Game Amount from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Game Sales


grouped <- vgsales  %>%                                 
  group_by(Year) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,gr_sum)

ax <- list(
  title = "Year"
)

ay <- list(
  title = " Game Sales per Year (in mio)"

)

filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'lines', fill = 'tozeroy' ,colors = myPalette) %>% 
  layout(title="Game Sales from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Sales per Game


grouped <- vgsales  %>%                                 
  group_by(Year) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,gr_sum)

ax <- list(
  title = "Year"
)

ay <- list(
  title = "Sales per Game"

)

filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'lines', fill = 'tozeroy' ,colors = myPalette) %>% 
  layout(title="Sales per Game from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Hier erkennen wir das 2008 und 2009 die Jahre waren in denen die Meisten Games Releast wurden und diese auch die meisten Verkäufe haben. Den größten per Game Verkaufswert gab es allerdings 1984,1985 und 1989. Neuere spiele hingegen verkaufen sich durchschnittlich schlechter was durch das größere Angebot auch zu erwarten ist.

Nun betrachten wir die Anzahl der Videospiele aufgelistet nach Platform.

Hierbei stellt sich die Frage ob ältere Plattformen mehr Spielereleases haben wovon auszugehen ist. Hierzu verwenden wir ein einfaches Balkendiagramm welche eine gute erste übersicht bietet.

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(Anzahl =n()) 

ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "Anzahl"
)
ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Platform,Anzahl, .desc="true"),
           y=~Anzahl,
           name="Game Amount by Platform" ,colors = myPalette) %>% 
  layout(title="Game Amount by Platform",
         xaxis = ax,
         yaxis = ay
         
         )

Dies lässt sich nicht generell bestätigen aber ein Trend ist definitiv erkennbar.

Nun stellt sich die Frage welche Plattform die meisten Sales hat.

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "Global Sales (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Platform,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Sales Amount by Platform" ,colors = myPalette) %>% 
  layout(title="Sales Amount by Platform",
         xaxis = ax,
         yaxis = ay
         )

Wie sich herausstellt ist dies jedoch nicht die Platform welches die meisten Gamereleases hat.

Nun analzsieren wir die unterschiede der Regionen.

Hierzu verwenden wir sowohl sorted bar plots sowie um einen besseren Überblick über die Prozentualverteilung der Konsolen in den einzelnen Regionen Pie charts.

Einzuwenden hierbei ist, dass die Regionen natürlich unterschiedlich viele Einwohner haben.Ein vergleich der absoluten Saleswerte ist hierbei natürlich nur wenig ausschlaggebend zeigt aber einen generellen beliebtheitstrend der Konsolen auf.

Platform Ranking

Balkendiagramme

Europa

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(EU_Sales))  %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "EU Sales (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Platform,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="EU Sales Amount by Platform" ,colors = myPalette) %>% 
  layout(title="EU Sales Amount by Platform",
         xaxis = ax,
         yaxis = ay
         )

Nord-Amerika

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(NA_Sales))  %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "NA Sales (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Platform,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="NA Sales Amount by Platform" ,colors = myPalette) %>% 
  layout(title="NA Sales Amount by Platform",
         xaxis = ax,
         yaxis = ay
         )

Japan

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(JP_Sales))  %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "JP Sales (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Platform,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="JP Sales Amount by Platform" ,colors = myPalette) %>% 
  layout(title="JP Sales Amount by Platform",
         xaxis = ax,
         yaxis = ay
         )

kreisdiagramme

Europa

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(EU_Sales))  %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "EU Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Platform,textinfo='label+percent',
           name="EU Sales Amount by Publisher" ,colors = myPalette) %>% 
  layout(title="EU Sales Amount by Publisher",
         xaxis = ax,
         yaxis = ay
         )

Nord-Amerika

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(NA_Sales))  %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "NA Sales (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Platform,textinfo='label+percent',
           name="NA Sales Amount by Publisher" ,colors = myPalette) %>% 
  layout(title="NA Sales Amount by Publisher",
         xaxis = ax,
         yaxis = ay
         )

Japan

grouped <- vgsales  %>% 
  group_by(Platform) %>% 
  summarize(sum(JP_Sales))  %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Platform <- as_factor(ordered$Platform)


ax <- list(
  title = "Platform"
)

ay <- list(
  title = "JP Sales (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Platform,textinfo='label+percent',
           name="JP Sales Amount by Platform" ,colors = myPalette) %>% 
  layout(title="JP Sales Amount by Platform",
         xaxis = ax,
         yaxis = ay
         )

Im genensatz zur EU, in der das japanische unternehmen Sony mit der PS2 und PS3 die liste anführt, hat in den USA das Landeseigene softwareunternehmen Microsoft mit der Xbox360 die Nase vorn. In Japan hingegen ist wie zu erwarten der japanische hersteller Nintendo mit dem DS der Markführer.

Um sich das Ganze etwas genauer anzuschauen betrachten wir die Anzahl der Sales per Platform im Verlauf der Jahre.

Um eine überladung des Diagramms zu verhindern werden hier allerdings nur Plattformen mit mindestens 60 mio in Sales im entsprechenden Jahr berücksichtigt. Dies hat den Nachteil das einige z.T wichtige Daten Fehlen, ein Weglassen ebenjenes Filters fürt aber zu kompletter Unübersichtlichkeit.


grouped <- vgsales  %>%                                 
  group_by(Year, Platform) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017')  %>% filter(gr_sum>60)%>%
  as.data.frame()
grouped <- grouped %>%arrange(desc(gr_sum)) %>% 
  group_by(Year, Platform) %>%
  slice(1:3)

filtered <- grouped %>% select(Year,Platform,gr_sum)
ax <- list(
  title = "Year"
)

ay <- list(
  title = "Sales per Platform (in mio)"

)


filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Platform ,colors = myPalette)%>% 
  layout(title="Sales per Platform from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Hier erkennen wir das Platform, wie zu erwarten, meist kurz nach Release die größten Verkaufszahlen verzeichnen.

Nun stellt sich die Frage ob sich neben bestimmten Platformen auch bestimmte Entwickler/Publisher häufen. Hierbei gehen wir davon aus das vermutlich Nintendo und EA die Liste anführen. Hierzu verwenden wir wiederum sorted Bar-Charts und kürzen die Namen um die Begriffe “Entertainment”, “Interactive”, “Game”, “Games” und “Studios” da dies die Namen nur unnötig verlängert und Filtern Publisher mit Geringen Anzahl an Game Releases.

Publisher

Amount

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n()) %>%  
  filter(Anzahl>100) %>% filter(Publisher!="Unknown")




PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)


ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "Anzahl"
)
ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Publisher,Anzahl, .desc="true"),
           y=~Anzahl,
           name="Game Amount by Publisher") %>% 
  layout(title="Game Amount by Publisher",
         xaxis = ax,
         yaxis = ay
         
         )

Sales

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(Global_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "Global Sales (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Sales Amount by Publisher"
           ,colors = myPalette) %>% 
  layout(title="Sales Amount by Publisher",
         xaxis = ax,
         yaxis = ay
         )

Auffällig ist hier die diskrepanz zwischen Anzahl der Spielereleases und Anzahl der Spieleverkäufe. Im gegensatz zu der Anzahl der Spiele (bei dem Nintendo nur auf platz 6 Sitz) dominiert Nintendo im anzahl der Sales.

Nun stellt sich wieder einmal die Frage ob sich dies in Bestimmten teilen der Welt unterscheidet und hierzu verwenden wir wiederum die SortedBar/Piechart kombo und die bereits genannten Filter

Publisher Ranking

Balkendiagramme

Europa

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(EU_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)


grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "EU Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="EU Sales Amount by Publisher"
           ,colors = myPalette) %>% 
  layout(title="EU Sales Amount by Publisher",
         xaxis = ax,
         yaxis = ay
         )

Nord Amerika

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(NA_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "NA Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="NA Sales Amount by Publisher"
           ,colors = myPalette) %>% 
  layout(title="NA Sales Amount by Publisher",
         xaxis = ax,
         yaxis = ay
         )

Japan

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(JP_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "JP Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Publisher,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="JP Sales Amount by Publisher"
           ,colors = myPalette) %>% 
  layout(title="JP Sales Amount by Publisher",
         xaxis = ax,
         yaxis = ay
         )

Kreisdiagramme

Europa

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(EU_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "EU Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Publisher,
           name="EU Sales Amount by Publisher"
          ,colors = myPalette) %>% 
  layout(title="EU Sales Amount by Publisher",
         xaxis = ax,
         yaxis = ay
         )

Nord-Amerika

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(NA_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "NA Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Publisher,textinfo='label+percent',
           name="NA Sales Amount by Publisher"
          ,colors = myPalette) %>% 
  layout(title="NA Sales Amount by Publisher",
         xaxis = ax,
         yaxis = ay
         )

Japan

grouped <- vgsales  %>% 
  group_by(Publisher) %>% 
  summarize(Anzahl =n(),sum(JP_Sales)) %>%
  filter(Anzahl>100) %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )

PublisherSales <- vgsales %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]
ordered$Publisher <-str_remove_all(ordered$Publisher, "Entertainment")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Interactive")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Studios")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Games")
ordered$Publisher <-str_remove_all(ordered$Publisher, "Game")
ordered$Publisher <- as_factor(ordered$Publisher)


ax <- list(
  title = "Publisher"
)

ay <- list(
  title = "JP Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Publisher,
           name="JP Sales Amount by Publisher"
          ,colors = myPalette) %>% 
  layout(title="JP Sales Amount by Publisher",
         xaxis = ax,
         yaxis = ay
         )

Zwischen EU und US lassen sich hier kaum Unterschiede feststellen in Japan hingegen ist eine verschiebung zu erkennen. Japanische Publisher führen hierbei die Liste an und drängen andere große unternehmen von den Top spots.

Nun schauen wir uns die Genreverteilung von Videospielen an. Hierzu verwenden wir wiederum die Altbekannte sorted Bar/Pie-Chart kombo.

Genre Amount

Balken Diagramm

grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(Anzahl =n())

grouped$Anzahl<-as_vector(grouped$Anzahl)
ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Genre <- as_factor(ordered$Genre)


ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Anzahl"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Genre,Anzahl, .desc="true"),
           y=~Anzahl,
           name="Amount by Genre"
           ,colors = myPalette) %>% 
  layout(title="Amount by Genre",
         xaxis = ax,
         yaxis = ay
         )

Kreis Diagramm

grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(Anzahl =n())

grouped$Anzahl<-as_vector(grouped$Anzahl)
ordered <- grouped[order(grouped$Anzahl), decreasing = FALSE]
ordered$Genre <- as_factor(ordered$Genre)


ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Anzahl"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Anzahl,labels=~Genre,
           name="Amount by Genre"
          ,colors = myPalette) %>% 
  layout(title="Amount by Genre",
         xaxis = ax,
         yaxis = ay
         )

Hierbei ist zu erkennen das Action und Sports ein Großteil (34%) der Genres ausmachen. Die Frage ist jedoch wie sind die Verkäufe verteilt und beeinflusst die anzahl der Games pro Genre irgendwie die Verkaufszahlen?

Sales Amount

Balken Diagramm


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Sales by Genre"
           ,colors = myPalette) %>% 
  layout(title="Sales by Genre",
         xaxis = ax,
         yaxis = ay
         )

Kreis Diagramm


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,
           name="Sales by Genre"
          ,colors = myPalette) %>% 
  layout(title="Sales by Genre",
         xaxis = ax,
         yaxis = ay
        )

Hierbei erkennen wir das es einige Unterschiede gibt Action und sports machen jedoch weiterhin einen Grosteil des Markts aus.

Nun schauen wir uns die Unterscheide in den Regionen an.

SalesbyGenre

Balkendiagramme

Europa


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(EU_Sales))  %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Sales by Genre (EU)"
           ,colors = myPalette) %>% 
  layout(title="Sales by Genre (EU)",
         xaxis = ax,
         yaxis = ay
         )

Nord-Amerika


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(NA_Sales))  %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Sales by Genre (NA)"
           ,colors = myPalette) %>% 
  layout(title="Sales by Genre (NA)",
         xaxis = ax,
         yaxis = ay
         )

Japan


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(JP_Sales))  %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales"

)

ordered%>%
  plot_ly() %>% 
  add_bars(x=~fct_reorder(Genre,Global_Sales, .desc="true"),
           y=~Global_Sales,
           name="Sales by Genre (JP)" ,colors = myPalette) %>% 
  layout(title="Sales by Genre (JP)",
         xaxis = ax,
         yaxis = ay
         )

Kreisdiagramme

Europa


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(EU_Sales))  %>%
rename(
    Global_Sales = "sum(EU_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales (in mio)"

)


ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,
           name="Sales by Genre (EU)" ,colors = myPalette) %>% 
  layout(title="Sales by Genre (EU)",
         xaxis = ax,
         yaxis = ay
        )

Nord-Amerika


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(NA_Sales))  %>%
rename(
    Global_Sales = "sum(NA_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales (in mio)"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,
           name="Sales by Genre (NA)",colors = myPalette) %>% 
  layout(title="Sales by Genre (NA)",
         xaxis = ax,
         yaxis = ay
        )

Japan


grouped <- vgsales  %>% 
  group_by(Genre) %>% 
  summarize(sum(JP_Sales))  %>%
rename(
    Global_Sales = "sum(JP_Sales)"
    )
grouped$Global_Sales<-as_vector(grouped$Global_Sales)
ordered <- grouped[order(grouped$Global_Sales), decreasing = FALSE]

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales"

)

ordered%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,
           name="Sales by Genre (JP)" ,colors = myPalette) %>% 
  layout(title="Sales by Genre (JP)",
         xaxis = ax,
         yaxis = ay
        )

Hierbei erkennen wir wieder einmal das US und EU recht ähnlich sind wohingegen Japan ein gänzlich anderes Genreshema erkennen lässt. In Japan dominiert Role-Playing welches sich in EU und US nur auf platz 7 befindet.

Nun schauen wir uns die Genreentwicklung über die Jahre an. Hierzu verwenden wir LinePlots.

Genre Amount per Year

Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
  title = "Year"
)

ay <- list(
  title = "Anzahl"

)

filtered %>%
plot_ly() %>% 
  add_lines(x=~Year,
           y=~Anzahl, color=~Genre,colors = myPalette)

Filled Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
  title = "Year"
)

ay <- list(
  title = "Anzahl"

)


filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'none', fill = 'tozeroy',color = ~Genre ,colors = myPalette)%>% 
  layout(title="Amount by Genre from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Stacked Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
  title = "Year"
)

ay <- list(
  title = "Anzahl"

)


filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Genre, colors = myPalette)%>% 
  layout(title="Amount by Genre from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )
NA

Genreshift %


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(Anzahl =n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,Anzahl)
ax <- list(
  title = "Year"
)

ay <- list(
  title = "Percent %"

)


filtered %>%
plot_ly(x = ~Year, y = ~Anzahl, type = 'scatter', mode = 'none', stackgroup = 'one',groupnorm = 'percent',color = ~Genre ,colors = myPalette)%>% 
  layout(title="Marketamount genreshift in % from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Hierbei zu erkennen ist Obwohl die Anzahl der Jährlichen Spielereleases über die Jahre hinweg stetig wächst bleiben die Meisten Genres ähnlich viel vertreten. Auffällig sind hierbei Strategy-Games die erst 1991 das erste mal auftretem Seitdem obwohl sie Leicht an Marketshare verlieren grob gleich bleiben. Außerdem sind Action Games die Spiele mit der wohl größten volatilität. Sind es 1982 noch fast 50% der Gamereleases fällt deren aufkommen 1084 schon auf nur noch knapp 10% ab und 1986 steigt der Wert wieder auf fast 30%. Dieser Trend setzt sich fort bis 1996 ab welchem Zeitpunkt sich Action Games von 3.6% über die Jahre bis 2016 bis 35% entwickeln.

Schauen wir uns an wie sich die verkäufe entwickelt haben.

Sales Amount per Year

Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,gr_sum)

ax <- list(
  title = "Year"
)

ay <- list(
  title = "Global_Sales"

)

filtered %>%
plot_ly() %>% 
  add_lines(x=~Year,
           y=~gr_sum, color=~Genre ,colors = myPalette) %>% 
  layout(title="Sales by Genre from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Filled Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,gr_sum)

ax <- list(
  title = "Year"
)

ay <- list(
  title = "Global_Sales"

)


filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', fill = 'tozeroy',color = ~Genre ,colors = myPalette) %>% 
  layout(title="Sales by Genre from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Stacked Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,gr_sum)

ax <- list(
  title = "Year"
)

ay <- list(
  title = "Global_Sales"

)


filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Genre ,colors = myPalette)%>% 
  layout(title="Sales by Genre from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Genreshift %


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,gr_sum)

ax <- list(
  title = "Year"
)

ay <- list(
  title = "Percent %"

)


filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',groupnorm = 'percent',color = ~Genre ,colors = myPalette)%>% 
  layout(title="Marketshare genreshift in % from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Wie zu erwarten lässt sich hier ein Großer overlap zu den Anzahl der Gamereleases feststellen.

Nun stellt sich die Frage hab sich die Verkäufe ähnlich der anzahl der GameReleases entwickelt?

Sales per Game per Year

Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
  title = "Year"
)

ay <- list(
  title = "Sales per Game"

)

filtered %>%
plot_ly() %>% 
  add_lines(x=~Year,
           y=~gr_sum, color=~Genre ,colors = myPalette) %>% 
  layout(title="Sales per Game by Genre from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Filled Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
  title = "Year"
)

ay <- list(
  title = "Sales per Game"

)

filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', fill = 'tozeroy',color = ~Genre ,colors = myPalette) %>% 
  layout(title="Sales per Game by Genre from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Stacked Lines


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
  title = "Year"
)

ay <- list(
  title = "Sales per Game"

)

filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',color = ~Genre, colors = myPalette)%>% 
  layout(title="Sales per Game by Genre from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Genreshift %


grouped <- vgsales  %>%                                 
  group_by(Year, Genre) %>%
  dplyr::summarize(gr_sum = sum(Global_Sales)/n()) %>% filter(Year!='N/A')%>%filter(Year!=2020) %>% filter(Year!='2017') %>%
  as.data.frame()


filtered <- grouped %>% select(Year,Genre,gr_sum)
ax <- list(
  title = "Year"
)

ay <- list(
  title = "Percent %"

)
filtered %>%
plot_ly(x = ~Year, y = ~gr_sum, type = 'scatter', mode = 'none', stackgroup = 'one',groupnorm = 'percent',color = ~Genre, colors = myPalette)%>% 
  layout(title="Marketshare in Sales per Game by Genre from 1980-2016",
         xaxis = ax,
         yaxis = ay
         )

Auch hier ist wie erwartet die Entwicklung Prozentual ähnlich sind. Auffällig ist jedoch das Shooter trotz ihrer geringen Vertretung in der Prozentualen Verteilung 1984 sowie 2014,2015 und 2016 die Nase Vorne haben. Platform Games haben 1985,1988 und 1990 die Nase Vorne. Die Hochzeit der Puzzle Games sind unangefochten 1988 mit dem Weltweitbekannten und auf Platz 6 der meistverkauften videospiele: Tetris. Ein genauerer vergleich der Ausschläge mit den dementsprechenden Videospielen wäre hier wünschenswert würde aber das Ausmaß dieser Arbeit sprengen.

Nun stellt sich die Frage wie es mit Genres pro publisher aussieht? Gibt es hier Publisher die verschiedene Genres bevorzugen bzw. deren Bestseller sich in bestimmten Genres Tummeln?

Hierzu verwenden wir ein stacked Bar-Plot. Dazu filtern wir die top 10 Publishern aka Publisher mit min 116 mio in Sales. Dies entfernt natürlich einiges an Information allerdings geht sonst einiges an Übersichtlichkeit verloren. Zusätzlich werden erneut die Worte “Entertainment”, “Interactive”, “Game”, “Games” und “Studios” entfernt.

Genre by Publisher

Sales



grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) 

PublisherSales <- grouped %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)

grouped <- grouped %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)

grouped$Publisher <-str_remove_all(grouped$Publisher, "Entertainment")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Interactive")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Studios")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Games")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Game")

  

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales"

)

grouped%>%
  plot_ly(x=~Publisher,
           y=~Global_Sales,
            type='bar',
           color=~Genre, colors = myPalette)  %>% 
  layout(title="Sales by Genre By Publisher",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack'
         )

Amount




grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(Anzahl =n(),sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    )

PublisherSales <- grouped %>% 
  group_by(Publisher) %>% 
  summarize(sum(Global_Sales)) %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% filter(Global_Sales>300)



grouped <- grouped  %>% filter(Publisher %in% PublisherSales$Publisher)

grouped$Global_Sales<-as_vector(grouped$Global_Sales)
grouped$Publisher <-str_remove_all(grouped$Publisher, "Entertainment")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Interactive")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Studios")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Games")
grouped$Publisher <-str_remove_all(grouped$Publisher, "Game")



ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Amount"

)

grouped%>%
  plot_ly(x=~Publisher,
           y=~Anzahl,
            type='bar',
           color=~Genre ,colors = myPalette)  %>% 
  layout(title="Amount by Genre By Publisher",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack'
         )

Bei dem vergleich der Werte ist hier zu bemerken, dass die meisten Publisher Hierbei sich mit der Anzahl der Spiele und den Sales gut abdecken. Die auffälligsten diskrepanzen sind hierbei EA mit dem Sports Genre und ihren järlich releasten Spielen FiFa/NBA2k etc. sowie Nintendo mit der Platformreihe Super Mario. Schauen wir uns diese Beiden Firmen Noch einmal im Detail an.

Hierzu verwenden wir wieder die Bar/Pie chart Combo die uns Bereits aus vorderen Teilen der Ausarbeitung bekannt sind.

Genre für Electronic Arts

Balkendiagramme

Sales



grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% 
  filter(Publisher == "Electronic Arts")


grouped$Global_Sales<-as_vector(grouped$Global_Sales)

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales"

)

grouped%>%
  plot_ly() %>% add_bars(x=~Genre,
           y=~Global_Sales,
           color=~Genre ,colors = myPalette)  %>% 
  layout(title="Sales by Genre for Electronic Arts",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack'
         )

Amount


grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(Anzahl =n())  %>% 
  filter(Publisher == "Electronic Arts")


ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Amount"

)


grouped%>%
  plot_ly() %>% add_bars(x=~Genre,
           y=~Anzahl,
           color=~Genre ,colors = myPalette)  %>% 
  layout(title="Amount by Genre for Electronic Arts ",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack'
         )

Kreisdiagramme

Sales



grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% 
  filter(Publisher == "Electronic Arts")


grouped$Global_Sales<-as_vector(grouped$Global_Sales)

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales"

)

grouped%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,textinfo='label+percent',sort = FALSE,
           name="Sales by Genre for Electronic Arts" ,colors = myPalette) %>% 
  layout(title="Sales by Genre for Electronic Arts",
         xaxis = ax,
         yaxis = ay
         )

Amount


grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(Anzahl =n())  %>% 
  filter(Publisher == "Electronic Arts")


ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Amount"

)

grouped%>%
  plot_ly() %>% 
  add_pie(values =~Anzahl,labels=~Genre,textinfo='label+percent',sort = FALSE,
           name="Amount by Genre for Electronic Arts" ,colors = myPalette) %>% 
  layout(title="Amount by Genre for Electronic Arts",
         xaxis = ax,
         yaxis = ay
         )

Schauen wir uns EA hier im Detail an fällt allerdings auf das die Diskrepanz zwischen Sales und Anzahl der Gamereleases für EA bei Sports gar nicht so groß ist (41.5% vs 43.2%). Die größeren diskrepanzen sind hier Shooter welches nur 10% der Gamereleases sind aber gut 15% der Sales und Action mit 13.5% der Gamereleases und 10.4% der Sales.

Schauen wir uns nun Nintendo an.

Genre für Nintendo

Balkendiagramme

Sales



grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% 
  filter(Publisher == "Nintendo")


grouped$Global_Sales<-as_vector(grouped$Global_Sales)

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales"

)

grouped%>%
  plot_ly() %>% add_bars(x=~Genre,
           y=~Global_Sales,
           color=~Genre ,colors = myPalette)  %>% 
  layout(title="Sales by Genre for Nintendo",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack'
         )

Amount


grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(Anzahl =n())  %>% 
  filter(Publisher == "Nintendo")


grouped$Global_Sales<-as_vector(grouped$Global_Sales)

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Amount"

)



grouped%>%
  plot_ly() %>% add_bars(x=~Genre,
           y=~Anzahl,
           color=~Genre ,colors = myPalette)  %>% 
  layout(title="Amount by Genre for Nintendo",
         xaxis = ax,
         yaxis = ay,
         barmode = 'stack'
         )

Kreisdiagramme

Sales



grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(sum(Global_Sales))  %>%
rename(
    Global_Sales = "sum(Global_Sales)"
    ) %>% 
  filter(Publisher == "Nintendo")


grouped$Global_Sales<-as_vector(grouped$Global_Sales)

ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Sales"

)

grouped%>%
  plot_ly() %>% 
  add_pie(values =~Global_Sales,labels=~Genre,textinfo='label+percent',sort = FALSE,
           name="Sales by Genre for Nintendo" ,colors = myPalette) %>% 
  layout(title="Sales by Genre for Nintendo",
         xaxis = ax,
         yaxis = ay
         )

Amount


grouped <- vgsales  %>% 
  group_by(Publisher,Genre) %>% 
  summarize(Anzahl =n())  %>% 
  filter(Publisher == "Nintendo")


ax <- list(
  title = "Genre"
)

ay <- list(
  title = "Amount"

)

grouped%>%
  plot_ly() %>% 
  add_pie(values =~Anzahl,labels=~Genre,textinfo='label+percent',sort = FALSE,
           name="Amount by Genre for Nintendo" ,colors = myPalette) %>% 
  layout(title="Amount by Genre for Nintendo",
         xaxis = ax,
         yaxis = ay
         )

Bei Nintendo zu erkennen ist hier, dass Platform spiele ein Kassenchlager sind. Nehmen diese nur 16% der spielereleases ein so bringen sie dennoch 24% der Sales ein. Gleiches Gilt für Sport games. 8% gegenüber 12%. Action (11% vs 7%), Misc (14% vs 10%) und Puzzle Games (10.5% vs 7%) sind jedoch nicht so erfolgreich.

Ausblick in die Zukunft

Ein Vergleich der Ausschläge mit den dementsprechenden Videospielen.

Eine genaue Analyse der Gamesales pro jahr (aka tetrist 1950 30 mal testris 2015 300000 mal) geben die daten nicht her.

eine anylse der Coronapandemie veränderungen (geben die daten nicht her)

LS0tDQp0aXRsZTogIlZEQSBQcm9qZWt0Ig0Kb3V0cHV0OiANCiAgIGh0bWxfZG9jdW1lbnQgOiANCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgIGh0bWxfbm90ZWJvb2sgOiANCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgIA0KLS0tDQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9VFJVRSwgZWNobz1UUlVFLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShmb3JjYXRzKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGtuaXRyLCB3YXJuLmNvbmZsaWN0cyA9IEZBTFNFLCBxdWlldGx5PVRSVUUpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkoZHlncmFwaHMpDQpsaWJyYXJ5KHh0cykNCm15UGFsZXR0ZSA8LSBicmV3ZXIucGFsKDEwLCAiUGFpcmVkIikNCnZnc2FsZXMgPC0gcmVhZF9jc3YoInZnc2FsZXMuY3N2IikNCmBgYA0KRGFzIHZlcndlbmRldGUgRGF0YXNldCBkZXMgUHJvamVrdHM6IGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvZ3JlZ29ydXQvdmlkZW9nYW1lc2FsZXMNCg0KRGllc2VzIERhdGFzZXQgdW1mYXNzdCB2ZXJzY2hpZWRlbmUgRGF0ZW4genUgVmlkZW9nYW1lcmVsZWFzZXMgdW5kIFNhbGVzIHp3aXNjaGVuIDE5ODAgdW5kIDIwMTYuDQoNCklkZWVuL1N0YXRlbWVudHM6DQoNCg0KQmVzdGltbXRlIEVudHdpY2tsZXIvUHVibGlzaGVyIGjDpHVmZW4gc2ljaCAoTmludGVuZG8vRUEpDQrDhGx0ZXJlIFBsYXR0Zm9ybWVuL3NwaWVsZSBoYWJlbiBtZWhyIHZlcmvDpHVmZSBiencgV2llIGhhdCBzaWNoIGRpZSBBbnphaGwgZGVyIHZlcmvDpHVmZSBpbSBsYXVmZSBkZXIgamFocmUgZW50d2lja2VsdD8NCkdlbnJlbmVudHdpY2tsdW5nIMO8YmVyIGRpZSBKYWhyZQ0KV2VsY2hlIFNwaWVsZS9QdWJsaXNoZXIvR2VucmVzIGluIHdlbGNoZW4gVGVpbGVuIGRlciB3ZWx0IHNpY2ggaMOkdWZlbiAoTmludGVuZG8gaW4gQXNpZW4sIFNob290ZXIgaW4gVVMvRVUpDQpHaWJ0IGVzIFN0YXRpc3Rpc2NoZSB6dXNhbW1lbmjDpG5nZSB6d2lzY2hlbiBlaW56ZWxuZW4gRmFrdG9yZW4gZS5nLiBHZW5yZSAtPiBTYWxlcw0KV2VsY2hlIEphaHJlIHNpbmQgZGllIGJlc3RlbiBpbiBkZXIgQW56YWhsIGRlciByZWxlYXN0ZW4gZ2FtZXMgdW5kIGjDpG5ndCBkaWVzIG1pdCBkZW4gU2FsZXMgenVzYW1tZW4/IChqZSBtZWhyIFRvdGFsIFNhbGVzIGRlc3RvIG1laHIgR2FtZXMgdmVya2F1ZmVuIHNpY2gpDQpXZWxjaGUgSmFocmUgc2luZCBkaWUgYmVzdGVuIGluIEFuemFobCBTYWxlcyBwcm8gZ2FtZSAobmV1ZXIgPSBiZXNzZXI/KQ0KV2VsY2hlIFBsYXR0Zm9ybSBpc3QgZGllIGJlc3RlIHVuZCB1bnRlcnNjaGVpZGV0IHNpY2ggZGllc2UgbmFjaCBSZWdpb24/DQpHaWJ0IGVzIFVudGVyc2NoaWVkZSBpbiBkZW4gUmVnaW9uZW4vaMOkbmd0IGRhcyBtaXQgZGVyIEFuemFobCBkZXIgRWlud29obmVyIGRlciBSZWdpb24genVzYW1tZW4/IChBc2lhPlVTPkVVKQ0KDQoNCg0KWnVlcnN0IHNjaGF1ZW4gd2lyIHVuZCBkaWUgQW56YWhsIGRlciBWaWRlb3NwaWVsZSB1bmQgZGllIEFuemFobCBkZXIgVmVya8OkdWZlIGltIGxhdWZlIGRlciBKYWhyZSBhbi4NCg0KSGllcnp1IHZlcndlbmRlbiB3aXIgTGluaWVuZGlhZ3JhbW1lLiBBdcOfZXJkZW0gZmlsdGVybiB3aXIgYWxsZSBEYXRlbnPDpHR6ZSBpbiBkZW5lbiBrZWluIEphaHIgYW5nZWdlYmVuIGlzdCBzb3dpZSBEYXRlbnPDpHR6ZSBtaXQgZGVuIEphaHJlbiAyMDE3IHVuZCAyMDIwIHVtIEZlaGxlcmhhZnRlIERhdGVuIHVuZCB1bnZvbGxzdMOkbmRpZ2UgRGF0ZW4gYXVzIGRlciBMaXN0ZSB6dSBlbnRmZXJuZW4uDQoNCiMjIEdhbWUgUmVsZWFzZXMgb3ZlciB0aGUgWWVhcnMgey50YWJzZXR9DQojIyMgR2FtZSBBbW91bnQgDQpgYGB7ciBwbG90KEFtb3VudEJ5WWVhciksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKEFuemFobCA9bigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEFuemFobCkNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW1vdW50Ig0KDQopDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+QW56YWhsLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJywgZmlsbCA9ICd0b3plcm95JyAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iR2FtZSBBbW91bnQgZnJvbSAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQojIyMgR2FtZSBTYWxlcw0KYGBge3IgcGxvdChHYW1lU2FsZXNCeVllYXIpLCBpbmNsdWRlPVRSVUUsIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLGdyX3N1bSkNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiIEdhbWUgU2FsZXMgcGVyIFllYXIgKGluIG1pbykiDQoNCikNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5ncl9zdW0sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLCBmaWxsID0gJ3RvemVyb3knICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJHYW1lIFNhbGVzIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KIyMjIFNhbGVzIHBlciBHYW1lDQpgYGB7ciBwbG90KFNhbGVzYnlHYW1lQnlZZWFyKSwgaW5jbHVkZT1UUlVFLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKS9uKCkpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsZ3Jfc3VtKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJZZWFyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyBwZXIgR2FtZSINCg0KKQ0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoeCA9IH5ZZWFyLCB5ID0gfmdyX3N1bSwgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsIGZpbGwgPSAndG96ZXJveScgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIHBlciBHYW1lIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KIyMgey19DQpIaWVyIGVya2VubmVuIHdpciBkYXMgMjAwOCB1bmQgMjAwOSBkaWUgSmFocmUgd2FyZW4gaW4gZGVuZW4gZGllIE1laXN0ZW4gR2FtZXMgUmVsZWFzdCB3dXJkZW4gdW5kIGRpZXNlIGF1Y2ggZGllIG1laXN0ZW4gVmVya8OkdWZlIGhhYmVuLg0KRGVuIGdyw7bDn3RlbiBwZXIgR2FtZSBWZXJrYXVmc3dlcnQgZ2FiIGVzIGFsbGVyZGluZ3MgMTk4NCwxOTg1IHVuZCAxOTg5LiBOZXVlcmUgc3BpZWxlIGhpbmdlZ2VuIHZlcmthdWZlbiBzaWNoIGR1cmNoc2Nobml0dGxpY2ggc2NobGVjaHRlciB3YXMgZHVyY2ggZGFzIGdyw7bDn2VyZSBBbmdlYm90IGF1Y2ggenUgZXJ3YXJ0ZW4gaXN0Lg0KDQpOdW4gYmV0cmFjaHRlbiB3aXIgZGllIEFuemFobCBkZXIgVmlkZW9zcGllbGUgYXVmZ2VsaXN0ZXQgbmFjaCBQbGF0Zm9ybS4NCmBgYHtyIG5vcGxvdCwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIGluY2x1ZGUgPUZBTFNFLH0NCnZnc2FsZXMgJT4lIA0KICBwbG90X2x5KA0KICAgIHg9flBsYXRmb3JtLA0KICAgIHN0cm9rZT1JKCJibGFjayIpLA0KICAgIG5hbWU9IkFtb3VudCBieSBQbGF0Zm9ybSIpICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGU9IkFtb3VudCBieSBQbGF0Zm9ybSIpDQp2Z3NhbGVzICU+JSANCiAgcGxvdF9seSAlPiUgDQogIGFkZF9ib3hwbG90KA0KICAgIHg9flBsYXRmb3JtLA0KICAgIHN0cm9rZT1JKCJibGFjayIpLA0KICAgIG5hbWU9IkFtb3VudCBieSBQbGF0Zm9ybSIpICU+JSANCiAgbGF5b3V0KA0KICAgIHRpdGxlPSJBbW91bnQgYnkgUGxhdGZvcm0iKQ0KDQp2Z3NhbGVzICU+JSANCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoDQogICAgeD1+R2xvYmFsX1NhbGVzLA0KICAgIHk9flBsYXRmb3JtLA0KICAgIG5hbWU9IlNhbGVzIGJ5IFBsYXRmb3JtIChpbiBtaW8pIikgJT4lIA0KICBsYXlvdXQoDQogICAgdGl0bGU9IlNhbGVzIGJ5IFBsYXRmb3JtIChpbiBtaW8pIikNCg0KYGBgDQpIaWVyYmVpIHN0ZWxsdCBzaWNoIGRpZSBGcmFnZSBvYiDDpGx0ZXJlIFBsYXR0Zm9ybWVuIG1laHIgU3BpZWxlcmVsZWFzZXMgaGFiZW4gd292b24gYXVzenVnZWhlbiBpc3QuDQpIaWVyenUgdmVyd2VuZGVuIHdpciBlaW4gZWluZmFjaGVzIEJhbGtlbmRpYWdyYW1tIHdlbGNoZSBlaW5lIGd1dGUgZXJzdGUgw7xiZXJzaWNodCBiaWV0ZXQuDQpgYGB7ciBwbG90LCBlY2hvID0gVFJVRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J21hcmt1cCcsfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFBsYXRmb3JtKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSkgDQoNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEFuemFobCksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCm9yZGVyZWQkUGxhdGZvcm0gPC0gYXNfZmFjdG9yKG9yZGVyZWQkUGxhdGZvcm0pDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUHVibGlzaGVyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbnphaGwiDQopDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKFBsYXRmb3JtLEFuemFobCwgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+QW56YWhsLA0KICAgICAgICAgICBuYW1lPSJHYW1lIEFtb3VudCBieSBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkdhbWUgQW1vdW50IGJ5IFBsYXRmb3JtIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICANCiAgICAgICAgICkNCmBgYA0KRGllcyBsw6Rzc3Qgc2ljaCBuaWNodCBnZW5lcmVsbCBiZXN0w6R0aWdlbiBhYmVyIGVpbiBUcmVuZCBpc3QgZGVmaW5pdGl2IGVya2VubmJhci4NCg0KDQpOdW4gc3RlbGx0IHNpY2ggZGllIEZyYWdlIHdlbGNoZSBQbGF0dGZvcm0gZGllIG1laXN0ZW4gU2FsZXMgaGF0Lg0KDQpgYGB7ciBwbG90KFBsYXRmb3JtUmFua2luZ19HbG9iYWwpLCBlY2hvID0gVFJVRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J21hcmt1cCcsfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFBsYXRmb3JtKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQbGF0Zm9ybSA8LSBhc19mYWN0b3Iob3JkZXJlZCRQbGF0Zm9ybSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQbGF0Zm9ybSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2xvYmFsIFNhbGVzIChpbiBtaW8pIg0KDQopDQoNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihQbGF0Zm9ybSxHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgQW1vdW50IGJ5IFBsYXRmb3JtIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgQW1vdW50IGJ5IFBsYXRmb3JtIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCldpZSBzaWNoIGhlcmF1c3N0ZWxsdCBpc3QgZGllcyBqZWRvY2ggbmljaHQgZGllIFBsYXRmb3JtIHdlbGNoZXMgZGllIG1laXN0ZW4gR2FtZXJlbGVhc2VzIGhhdC4NCg0KTnVuIGFuYWx6c2llcmVuIHdpciBkaWUgdW50ZXJzY2hpZWRlIGRlciBSZWdpb25lbi4NCg0KSGllcnp1IHZlcndlbmRlbiB3aXIgc293b2hsIHNvcnRlZCBiYXIgcGxvdHMgc293aWUgdW0gZWluZW4gYmVzc2VyZW4gw5xiZXJibGljayDDvGJlciBkaWUgUHJvemVudHVhbHZlcnRlaWx1bmcgZGVyIEtvbnNvbGVuIGluIGRlbiBlaW56ZWxuZW4gUmVnaW9uZW4gUGllIGNoYXJ0cy4NCg0KRWluenV3ZW5kZW4gaGllcmJlaSBpc3QsIGRhc3MgZGllIFJlZ2lvbmVuIG5hdMO8cmxpY2ggdW50ZXJzY2hpZWRsaWNoIHZpZWxlIEVpbndvaG5lciBoYWJlbi5FaW4gdmVyZ2xlaWNoIGRlciBhYnNvbHV0ZW4gU2FsZXN3ZXJ0ZSBpc3QgaGllcmJlaSBuYXTDvHJsaWNoIG51ciB3ZW5pZyBhdXNzY2hsYWdnZWJlbmQgemVpZ3QgYWJlciBlaW5lbiBnZW5lcmVsbGVuIGJlbGllYnRoZWl0c3RyZW5kIGRlciBLb25zb2xlbiBhdWYuDQoNCiMjIFBsYXRmb3JtIFJhbmtpbmcgey50YWJzZXR9DQoNCiMjIyBCYWxrZW5kaWFncmFtbWUgey50YWJzZXR9DQojIyMjIEV1cm9wYQ0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfRVUxKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEVVX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oRVVfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJFVSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUGxhdGZvcm0sR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9IkVVIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkVVIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQojIyMjIE5vcmQtQW1lcmlrYQ0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfTkExKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKE5BX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJOQSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUGxhdGZvcm0sR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9Ik5BIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9Ik5BIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIyMgSmFwYW4NCmBgYHtyIHBsb3QoUGxhdGZvcm1SYW5raW5nX0pQMSksIGVjaG8gPSBUUlVFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0nbWFya3VwJyx9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUGxhdGZvcm0pICU+JSANCiAgc3VtbWFyaXplKHN1bShKUF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEpQX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQbGF0Zm9ybSA8LSBhc19mYWN0b3Iob3JkZXJlZCRQbGF0Zm9ybSkNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQbGF0Zm9ybSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiSlAgU2FsZXMgKGluIG1pbykiDQoNCikNCg0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKFBsYXRmb3JtLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJKUCBTYWxlcyBBbW91bnQgYnkgUGxhdGZvcm0iICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJKUCBTYWxlcyBBbW91bnQgYnkgUGxhdGZvcm0iLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KIyMjIGtyZWlzZGlhZ3JhbW1lIHsudGFic2V0fQ0KDQojIyMjIEV1cm9wYQ0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfRVUyKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEVVX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oRVVfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJFVSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+UGxhdGZvcm0sdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnLA0KICAgICAgICAgICBuYW1lPSJFVSBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iRVUgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQojIyMjIE5vcmQtQW1lcmlrYQ0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfTkEyKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKE5BX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oTkFfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJOQSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5QbGF0Zm9ybSx0ZXh0aW5mbz0nbGFiZWwrcGVyY2VudCcsDQogICAgICAgICAgIG5hbWU9Ik5BIFNhbGVzIEFtb3VudCBieSBQdWJsaXNoZXIiICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJOQSBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KIyMjIyBKYXBhbg0KYGBge3IgcGxvdChQbGF0Zm9ybVJhbmtpbmdfSlAyKSwgZWNobyA9IFRSVUUsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdtYXJrdXAnLH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQbGF0Zm9ybSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEpQX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oSlBfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFBsYXRmb3JtIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFBsYXRmb3JtKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlBsYXRmb3JtIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJKUCBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5QbGF0Zm9ybSx0ZXh0aW5mbz0nbGFiZWwrcGVyY2VudCcsDQogICAgICAgICAgIG5hbWU9IkpQIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkpQIFNhbGVzIEFtb3VudCBieSBQbGF0Zm9ybSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCg0KIyMgey19DQpJbSBnZW5lbnNhdHogenVyIEVVLCBpbiBkZXIgZGFzIGphcGFuaXNjaGUgdW50ZXJuZWhtZW4gU29ueSBtaXQgZGVyIFBTMiB1bmQgUFMzIGRpZSBsaXN0ZSBhbmbDvGhydCwgaGF0IGluIGRlbiBVU0EgZGFzIExhbmRlc2VpZ2VuZSBzb2Z0d2FyZXVudGVybmVobWVuIE1pY3Jvc29mdCBtaXQgZGVyIFhib3gzNjAgZGllIE5hc2Ugdm9ybi4gSW4gSmFwYW4gaGluZ2VnZW4gaXN0IHdpZSB6dSBlcndhcnRlbiBkZXIgamFwYW5pc2NoZSBoZXJzdGVsbGVyIE5pbnRlbmRvIG1pdCBkZW0gRFMgZGVyIE1hcmtmw7xocmVyLg0KDQpVbSBzaWNoIGRhcyBHYW56ZSBldHdhcyBnZW5hdWVyIGFuenVzY2hhdWVuIGJldHJhY2h0ZW4gd2lyIGRpZSBBbnphaGwgZGVyIFNhbGVzIHBlciBQbGF0Zm9ybSBpbSBWZXJsYXVmIGRlciBKYWhyZS4NCg0KVW0gZWluZSDDvGJlcmxhZHVuZyBkZXMgRGlhZ3JhbW1zIHp1IHZlcmhpbmRlcm4gd2VyZGVuIGhpZXIgYWxsZXJkaW5ncyBudXIgUGxhdHRmb3JtZW4gbWl0IG1pbmRlc3RlbnMgNjAgbWlvIGluIFNhbGVzIGltIGVudHNwcmVjaGVuZGVuIEphaHIgYmVyw7xja3NpY2h0aWd0LiBEaWVzIGhhdCBkZW4gTmFjaHRlaWwgZGFzIGVpbmlnZSB6LlQgd2ljaHRpZ2UgRGF0ZW4gRmVobGVuLCBlaW4gV2VnbGFzc2VuIGViZW5qZW5lcyBGaWx0ZXJzIGbDvHJ0IGFiZXIgenUga29tcGxldHRlciBVbsO8YmVyc2ljaHRsaWNoa2VpdC4NCmBgYHtyIHBsb3QoU2FsZXNQZXJQbGF0Zm9ybWJ5WWVhciksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIGdyb3VwX2J5KFllYXIsIFBsYXRmb3JtKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShncl9zdW0gPSBzdW0oR2xvYmFsX1NhbGVzKSkgJT4lIGZpbHRlcihZZWFyIT0nTi9BJyklPiVmaWx0ZXIoWWVhciE9MjAyMCkgJT4lIGZpbHRlcihZZWFyIT0nMjAxNycpICAlPiUgZmlsdGVyKGdyX3N1bT42MCklPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQpncm91cGVkIDwtIGdyb3VwZWQgJT4lYXJyYW5nZShkZXNjKGdyX3N1bSkpICU+JSANCiAgZ3JvdXBfYnkoWWVhciwgUGxhdGZvcm0pICU+JQ0KICBzbGljZSgxOjMpDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLFBsYXRmb3JtLGdyX3N1bSkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlllYXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIHBlciBQbGF0Zm9ybSAoaW4gbWlvKSINCg0KKQ0KDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+Z3Jfc3VtLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBzdGFja2dyb3VwID0gJ29uZScsY29sb3IgPSB+UGxhdGZvcm0gLGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgcGVyIFBsYXRmb3JtIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KSGllciBlcmtlbm5lbiB3aXIgZGFzIFBsYXRmb3JtLCB3aWUgenUgZXJ3YXJ0ZW4sIG1laXN0IGt1cnogbmFjaCBSZWxlYXNlIGRpZSBncsO2w590ZW4gVmVya2F1ZnN6YWhsZW4gdmVyemVpY2huZW4uDQoNCg0KDQoNCk51biBzdGVsbHQgc2ljaCBkaWUgRnJhZ2Ugb2Igc2ljaCBuZWJlbiBiZXN0aW1tdGVuIFBsYXRmb3JtZW4gYXVjaCBiZXN0aW1tdGUgRW50d2lja2xlci9QdWJsaXNoZXIgaMOkdWZlbi4gSGllcmJlaSBnZWhlbiB3aXIgZGF2b24gYXVzIGRhcyB2ZXJtdXRsaWNoIE5pbnRlbmRvIHVuZCBFQSBkaWUgTGlzdGUgYW5mw7xocmVuLg0KSGllcnp1IHZlcndlbmRlbiB3aXIgd2llZGVydW0gc29ydGVkIEJhci1DaGFydHMgdW5kIGvDvHJ6ZW4gZGllIE5hbWVuIHVtIGRpZSBCZWdyaWZmZSAiRW50ZXJ0YWlubWVudCIsICJJbnRlcmFjdGl2ZSIsICJHYW1lIiwgIkdhbWVzIiB1bmQgIlN0dWRpb3MiIGRhIGRpZXMgZGllIE5hbWVuIG51ciB1bm7DtnRpZyB2ZXJsw6RuZ2VydCB1bmQgRmlsdGVybiBQdWJsaXNoZXIgbWl0IEdlcmluZ2VuIEFuemFobCBhbiBHYW1lIFJlbGVhc2VzLg0KDQojIyBQdWJsaXNoZXIgey50YWJzZXR9DQoNCiMjIyBBbW91bnQNCmBgYHtyIHBsb3QyLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCkpICU+JSAgDQogIGZpbHRlcihBbnphaGw+MTAwKSAlPiUgZmlsdGVyKFB1Ymxpc2hlciE9IlVua25vd24iKQ0KDQoNCg0KDQpQdWJsaXNoZXJTYWxlcyA8LSB2Z3NhbGVzICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQoNCg0KZ3JvdXBlZCA8LSBncm91cGVkICAlPiUgZmlsdGVyKFB1Ymxpc2hlciAlaW4lIFB1Ymxpc2hlclNhbGVzJFB1Ymxpc2hlcikNCg0KDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRBbnphaGwpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFuemFobCINCikNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUHVibGlzaGVyLEFuemFobCwgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+QW56YWhsLA0KICAgICAgICAgICBuYW1lPSJHYW1lIEFtb3VudCBieSBQdWJsaXNoZXIiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJHYW1lIEFtb3VudCBieSBQdWJsaXNoZXIiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgIA0KICAgICAgICAgKQ0KYGBgDQojIyMgU2FsZXMNCmBgYHtyIHBsb3QoUHVibGlzaGVyUmFua2luZ19HbG9iYWwpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCksc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KICBmaWx0ZXIoQW56YWhsPjEwMCkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gdmdzYWxlcyAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkVudGVydGFpbm1lbnQiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkludGVyYWN0aXZlIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJTdHVkaW9zIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LSBhc19mYWN0b3Iob3JkZXJlZCRQdWJsaXNoZXIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUHVibGlzaGVyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJHbG9iYWwgU2FsZXMgKGluIG1pbykiDQoNCikNCg0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKFB1Ymxpc2hlcixHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciINCiAgICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIEFtb3VudCBieSBQdWJsaXNoZXIiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KIyMgey19DQpBdWZmw6RsbGlnIGlzdCBoaWVyIGRpZSBkaXNrcmVwYW56IHp3aXNjaGVuIEFuemFobCBkZXIgU3BpZWxlcmVsZWFzZXMgdW5kIEFuemFobCBkZXIgU3BpZWxldmVya8OkdWZlLiBJbSBnZWdlbnNhdHogenUgZGVyIEFuemFobCBkZXIgU3BpZWxlIChiZWkgZGVtIE5pbnRlbmRvIG51ciBhdWYgcGxhdHogNiBTaXR6KSBkb21pbmllcnQgTmludGVuZG8gaW0gYW56YWhsIGRlciBTYWxlcy4NCg0KDQpOdW4gc3RlbGx0IHNpY2ggd2llZGVyIGVpbm1hbCBkaWUgRnJhZ2Ugb2Igc2ljaCBkaWVzIGluIEJlc3RpbW10ZW4gdGVpbGVuIGRlciBXZWx0IHVudGVyc2NoZWlkZXQgdW5kIGhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIHdpZWRlcnVtIGRpZSBTb3J0ZWRCYXIvUGllY2hhcnQga29tYm8gdW5kIGRpZSBiZXJlaXRzIGdlbmFubnRlbiBGaWx0ZXINCg0KIyMgUHVibGlzaGVyIFJhbmtpbmcgey50YWJzZXR9DQoNCiMjIyBCYWxrZW5kaWFncmFtbWUgey50YWJzZXR9DQojIyMjIEV1cm9wYQ0KDQpgYGB7ciBwbG90KFB1Ymxpc2hlclJhbmtpbmdfRVUxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpLHN1bShFVV9TYWxlcykpICU+JQ0KICBmaWx0ZXIoQW56YWhsPjEwMCkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShFVV9TYWxlcykiDQogICAgKQ0KDQpQdWJsaXNoZXJTYWxlcyA8LSB2Z3NhbGVzICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQoNCg0KZ3JvdXBlZCA8LSBncm91cGVkICAlPiUgZmlsdGVyKFB1Ymxpc2hlciAlaW4lIFB1Ymxpc2hlclNhbGVzJFB1Ymxpc2hlcikNCg0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkVudGVydGFpbm1lbnQiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkludGVyYWN0aXZlIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJTdHVkaW9zIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LSBhc19mYWN0b3Iob3JkZXJlZCRQdWJsaXNoZXIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUHVibGlzaGVyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJFVSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKFB1Ymxpc2hlcixHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iRVUgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciINCiAgICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkVVIFNhbGVzIEFtb3VudCBieSBQdWJsaXNoZXIiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KIyMjIyBOb3JkIEFtZXJpa2ENCmBgYHtyIHBsb3QoUHVibGlzaGVyUmFua2luZ19OQTEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCksc3VtKE5BX1NhbGVzKSkgJT4lDQogIGZpbHRlcihBbnphaGw+MTAwKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKE5BX1NhbGVzKSINCiAgICApDQoNClB1Ymxpc2hlclNhbGVzIDwtIHZnc2FsZXMgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSAlPiUgZmlsdGVyKEdsb2JhbF9TYWxlcz4zMDApDQoNCg0KDQpncm91cGVkIDwtIGdyb3VwZWQgICU+JSBmaWx0ZXIoUHVibGlzaGVyICVpbiUgUHVibGlzaGVyU2FsZXMkUHVibGlzaGVyKQ0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkVudGVydGFpbm1lbnQiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkludGVyYWN0aXZlIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJTdHVkaW9zIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LSBhc19mYWN0b3Iob3JkZXJlZCRQdWJsaXNoZXIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUHVibGlzaGVyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJOQSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9iYXJzKHg9fmZjdF9yZW9yZGVyKFB1Ymxpc2hlcixHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iTkEgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciINCiAgICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9Ik5BIFNhbGVzIEFtb3VudCBieSBQdWJsaXNoZXIiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KIyMjIyBKYXBhbg0KYGBge3IgcGxvdChQdWJsaXNoZXJSYW5raW5nX0pQMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSxzdW0oSlBfU2FsZXMpKSAlPiUNCiAgZmlsdGVyKEFuemFobD4xMDApICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oSlBfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gdmdzYWxlcyAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkpQIFNhbGVzIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoUHVibGlzaGVyLEdsb2JhbF9TYWxlcywgLmRlc2M9InRydWUiKSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBuYW1lPSJKUCBTYWxlcyBBbW91bnQgYnkgUHVibGlzaGVyIg0KICAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iSlAgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIyBLcmVpc2RpYWdyYW1tZSB7LnRhYnNldH0NCg0KIyMjIyBFdXJvcGENCg0KYGBge3IgcGxvdChQdWJsaXNoZXJSYW5raW5nX0VVKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpLHN1bShFVV9TYWxlcykpICU+JQ0KICBmaWx0ZXIoQW56YWhsPjEwMCkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShFVV9TYWxlcykiDQogICAgKQ0KDQpQdWJsaXNoZXJTYWxlcyA8LSB2Z3NhbGVzICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIGZpbHRlcihHbG9iYWxfU2FsZXM+MzAwKQ0KDQoNCg0KZ3JvdXBlZCA8LSBncm91cGVkICAlPiUgZmlsdGVyKFB1Ymxpc2hlciAlaW4lIFB1Ymxpc2hlclNhbGVzJFB1Ymxpc2hlcikNCg0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJFbnRlcnRhaW5tZW50IikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJJbnRlcmFjdGl2ZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiU3R1ZGlvcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZXMiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC0gYXNfZmFjdG9yKG9yZGVyZWQkUHVibGlzaGVyKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlB1Ymxpc2hlciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiRVUgU2FsZXMgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkdsb2JhbF9TYWxlcyxsYWJlbHM9flB1Ymxpc2hlciwNCiAgICAgICAgICAgbmFtZT0iRVUgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciINCiAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iRVUgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIyMgTm9yZC1BbWVyaWthDQoNCmBgYHtyIHBsb3QoUHVibGlzaGVyUmFua2luZ19OQTIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCksc3VtKE5BX1NhbGVzKSkgJT4lDQogIGZpbHRlcihBbnphaGw+MTAwKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKE5BX1NhbGVzKSINCiAgICApDQoNClB1Ymxpc2hlclNhbGVzIDwtIHZnc2FsZXMgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSAlPiUgZmlsdGVyKEdsb2JhbF9TYWxlcz4zMDApDQoNCg0KDQpncm91cGVkIDwtIGdyb3VwZWQgICU+JSBmaWx0ZXIoUHVibGlzaGVyICVpbiUgUHVibGlzaGVyU2FsZXMkUHVibGlzaGVyKQ0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkVudGVydGFpbm1lbnQiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkludGVyYWN0aXZlIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJTdHVkaW9zIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lcyIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiR2FtZSIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LSBhc19mYWN0b3Iob3JkZXJlZCRQdWJsaXNoZXIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiUHVibGlzaGVyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJOQSBTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+UHVibGlzaGVyLHRleHRpbmZvPSdsYWJlbCtwZXJjZW50JywNCiAgICAgICAgICAgbmFtZT0iTkEgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciINCiAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iTkEgU2FsZXMgQW1vdW50IGJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIyMgSmFwYW4NCg0KYGBge3IgcGxvdChQdWJsaXNoZXJSYW5raW5nX0pQMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSxzdW0oSlBfU2FsZXMpKSAlPiUNCiAgZmlsdGVyKEFuemFobD4xMDApICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oSlBfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gdmdzYWxlcyAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpvcmRlcmVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKG9yZGVyZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0Kb3JkZXJlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChvcmRlcmVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwob3JkZXJlZCRQdWJsaXNoZXIsICJHYW1lIikNCm9yZGVyZWQkUHVibGlzaGVyIDwtIGFzX2ZhY3RvcihvcmRlcmVkJFB1Ymxpc2hlcikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJQdWJsaXNoZXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkpQIFNhbGVzIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5QdWJsaXNoZXIsDQogICAgICAgICAgIG5hbWU9IkpQIFNhbGVzIEFtb3VudCBieSBQdWJsaXNoZXIiDQogICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkpQIFNhbGVzIEFtb3VudCBieSBQdWJsaXNoZXIiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQojIyB7LX0NCg0KWndpc2NoZW4gRVUgdW5kIFVTIGxhc3NlbiBzaWNoIGhpZXIga2F1bSBVbnRlcnNjaGllZGUgZmVzdHN0ZWxsZW4gaW4gSmFwYW4gaGluZ2VnZW4gaXN0IGVpbmUgdmVyc2NoaWVidW5nIHp1IGVya2VubmVuLiBKYXBhbmlzY2hlIFB1Ymxpc2hlciBmw7xocmVuIGhpZXJiZWkgZGllIExpc3RlIGFuIHVuZCBkcsOkbmdlbiBhbmRlcmUgZ3Jvw59lIHVudGVybmVobWVuIHZvbiBkZW4gVG9wIHNwb3RzLg0KDQpOdW4gc2NoYXVlbiB3aXIgdW5zIGRpZSBHZW5yZXZlcnRlaWx1bmcgdm9uIFZpZGVvc3BpZWxlbiBhbi4gSGllcnp1IHZlcndlbmRlbiB3aXIgd2llZGVydW0gZGllIEFsdGJla2FubnRlIHNvcnRlZCBCYXIvUGllLUNoYXJ0IGtvbWJvLg0KDQojIyBHZW5yZSBBbW91bnQgey50YWJzZXR9DQoNCiMjIyBCYWxrZW4gRGlhZ3JhbW0NCg0KYGBge3IgcGxvdChHZW5yZUFtb3VudF9HTG9iYWwxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCkpDQoNCmdyb3VwZWQkQW56YWhsPC1hc192ZWN0b3IoZ3JvdXBlZCRBbnphaGwpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRBbnphaGwpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJEdlbnJlIDwtIGFzX2ZhY3RvcihvcmRlcmVkJEdlbnJlKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbnphaGwiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihHZW5yZSxBbnphaGwsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkFuemFobCwNCiAgICAgICAgICAgbmFtZT0iQW1vdW50IGJ5IEdlbnJlIg0KICAgICAgICAgICAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iQW1vdW50IGJ5IEdlbnJlIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQojIyMgS3JlaXMgRGlhZ3JhbW0NCg0KYGBge3IgcGxvdChHZW5yZUFtb3VudF9HTG9iYWwyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCkpDQoNCmdyb3VwZWQkQW56YWhsPC1hc192ZWN0b3IoZ3JvdXBlZCRBbnphaGwpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRBbnphaGwpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQpvcmRlcmVkJEdlbnJlIDwtIGFzX2ZhY3RvcihvcmRlcmVkJEdlbnJlKQ0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbnphaGwiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkFuemFobCxsYWJlbHM9fkdlbnJlLA0KICAgICAgICAgICBuYW1lPSJBbW91bnQgYnkgR2VucmUiDQogICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkFtb3VudCBieSBHZW5yZSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIHstfQ0KDQpIaWVyYmVpIGlzdCB6dSBlcmtlbm5lbiBkYXMgQWN0aW9uIHVuZCBTcG9ydHMgZWluIEdyb8OfdGVpbCAoMzQlKSBkZXIgR2VucmVzIGF1c21hY2hlbi4gRGllIEZyYWdlIGlzdCBqZWRvY2ggd2llIHNpbmQgZGllIFZlcmvDpHVmZSB2ZXJ0ZWlsdCB1bmQgYmVlaW5mbHVzc3QgZGllIGFuemFobCBkZXIgR2FtZXMgcHJvIEdlbnJlIGlyZ2VuZHdpZSBkaWUgVmVya2F1ZnN6YWhsZW4/DQoNCiMjIFNhbGVzIEFtb3VudCB7LnRhYnNldH0NCg0KIyMjIEJhbGtlbiBEaWFncmFtbQ0KDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZV9HbG9iYWwxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiU2FsZXMgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihHZW5yZSxHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgYnkgR2VucmUiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBieSBHZW5yZSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANCg0KIyMjIEtyZWlzIERpYWdyYW1tDQoNCmBgYHtyIHBsb3QoU2FsZXNCeUdlbnJlX0dsb2JhbDIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoR2VucmUpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpvcmRlcmVkIDwtIGdyb3VwZWRbb3JkZXIoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpLCBkZWNyZWFzaW5nID0gRkFMU0VdDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyAoaW4gbWlvKSINCg0KKQ0KDQpvcmRlcmVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+R2VucmUsDQogICAgICAgICAgIG5hbWU9IlNhbGVzIGJ5IEdlbnJlIg0KICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBieSBHZW5yZSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICApDQpgYGANCg0KDQojIyB7LX0NCg0KSGllcmJlaSBlcmtlbm5lbiB3aXIgZGFzIGVzIGVpbmlnZSBVbnRlcnNjaGllZGUgZ2lidCBBY3Rpb24gdW5kIHNwb3J0cyBtYWNoZW4gamVkb2NoIHdlaXRlcmhpbiBlaW5lbiBHcm9zdGVpbCBkZXMgTWFya3RzIGF1cy4NCg0KTnVuIHNjaGF1ZW4gd2lyIHVucyBkaWUgVW50ZXJzY2hlaWRlIGluIGRlbiBSZWdpb25lbiBhbi4NCg0KIyMgU2FsZXNieUdlbnJlIHsudGFic2V0fQ0KDQojIyMgQmFsa2VuZGlhZ3JhbW1lIHsudGFic2V0fQ0KDQojIyMjIEV1cm9wYQ0KDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZV9FVTEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoR2VucmUpICU+JSANCiAgc3VtbWFyaXplKHN1bShFVV9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEVVX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiU2FsZXMgKGluIG1pbykiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihHZW5yZSxHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgYnkgR2VucmUgKEVVKSINCiAgICAgICAgICAgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIChFVSkiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQojIyMjIE5vcmQtQW1lcmlrYQ0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVfTkExKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oTkFfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShOQV9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX2JhcnMoeD1+ZmN0X3Jlb3JkZXIoR2VucmUsR2xvYmFsX1NhbGVzLCAuZGVzYz0idHJ1ZSIpLA0KICAgICAgICAgICB5PX5HbG9iYWxfU2FsZXMsDQogICAgICAgICAgIG5hbWU9IlNhbGVzIGJ5IEdlbnJlIChOQSkiDQogICAgICAgICAgICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBieSBHZW5yZSAoTkEpIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KIyMjIyBKYXBhbg0KDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZV9KUDEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoR2VucmUpICU+JSANCiAgc3VtbWFyaXplKHN1bShKUF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEpQX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiU2FsZXMiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfYmFycyh4PX5mY3RfcmVvcmRlcihHZW5yZSxHbG9iYWxfU2FsZXMsIC5kZXNjPSJ0cnVlIiksDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgYnkgR2VucmUgKEpQKSIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIChKUCkiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQoNCg0KIyMjIEtyZWlzZGlhZ3JhbW1lIHsudGFic2V0fQ0KDQojIyMjIEV1cm9wYQ0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVfRVUyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oRVVfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShFVV9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIChpbiBtaW8pIg0KDQopDQoNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkdsb2JhbF9TYWxlcyxsYWJlbHM9fkdlbnJlLA0KICAgICAgICAgICBuYW1lPSJTYWxlcyBieSBHZW5yZSAoRVUpIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgYnkgR2VucmUgKEVVKSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICApDQpgYGANCg0KIyMjIyBOb3JkLUFtZXJpa2ENCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVfTkEyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oTkFfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShOQV9TYWxlcykiDQogICAgKQ0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCm9yZGVyZWQgPC0gZ3JvdXBlZFtvcmRlcihncm91cGVkJEdsb2JhbF9TYWxlcyksIGRlY3JlYXNpbmcgPSBGQUxTRV0NCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIChpbiBtaW8pIg0KDQopDQoNCm9yZGVyZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5HbG9iYWxfU2FsZXMsbGFiZWxzPX5HZW5yZSwNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgYnkgR2VucmUgKE5BKSIsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgYnkgR2VucmUgKE5BKSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICApDQpgYGANCg0KIyMjIyBKYXBhbg0KDQpgYGB7ciBwbG90KFNhbGVzQnlHZW5yZV9KUDIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoR2VucmUpICU+JSANCiAgc3VtbWFyaXplKHN1bShKUF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEpQX1NhbGVzKSINCiAgICApDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0Kb3JkZXJlZCA8LSBncm91cGVkW29yZGVyKGdyb3VwZWQkR2xvYmFsX1NhbGVzKSwgZGVjcmVhc2luZyA9IEZBTFNFXQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiU2FsZXMiDQoNCikNCg0Kb3JkZXJlZCU+JQ0KICBwbG90X2x5KCkgJT4lIA0KICBhZGRfcGllKHZhbHVlcyA9fkdsb2JhbF9TYWxlcyxsYWJlbHM9fkdlbnJlLA0KICAgICAgICAgICBuYW1lPSJTYWxlcyBieSBHZW5yZSAoSlApIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgYnkgR2VucmUgKEpQKSIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICApDQpgYGANCg0KIyMgey19DQpIaWVyYmVpIGVya2VubmVuIHdpciB3aWVkZXIgZWlubWFsIGRhcyBVUyB1bmQgRVUgcmVjaHQgw6RobmxpY2ggc2luZCB3b2hpbmdlZ2VuIEphcGFuIGVpbiBnw6RuemxpY2ggYW5kZXJlcyBHZW5yZXNoZW1hIGVya2VubmVuIGzDpHNzdC4gSW4gSmFwYW4gZG9taW5pZXJ0IFJvbGUtUGxheWluZyB3ZWxjaGVzIHNpY2ggaW4gRVUgdW5kIFVTIG51ciBhdWYgcGxhdHogNyBiZWZpbmRldC4NCg0KTnVuIHNjaGF1ZW4gd2lyIHVucyBkaWUgR2VucmVlbnR3aWNrbHVuZyDDvGJlciBkaWUgSmFocmUgYW4uIEhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIExpbmVQbG90cy4NCg0KIyMgR2VucmUgQW1vdW50IHBlciBZZWFyIHsudGFic2V0fQ0KDQojIyMgTGluZXMNCg0KYGBge3IgcGxvdChBbW91bnRPZkdhbWVzQnlHZW5yZWJ5WWVhcjEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoQW56YWhsID1uKCkpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsQW56YWhsKQ0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KDQopDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSgpICU+JSANCiAgYWRkX2xpbmVzKHg9flllYXIsDQogICAgICAgICAgIHk9fkFuemFobCwgY29sb3I9fkdlbnJlLGNvbG9ycyA9IG15UGFsZXR0ZSkNCg0KYGBgDQoNCiMjIyBGaWxsZWQgTGluZXMNCg0KYGBge3IgcGxvdChBbW91bnRPZkdhbWVzQnlHZW5yZWJ5WWVhcjIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoQW56YWhsID1uKCkpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsQW56YWhsKQ0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KDQopDQoNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5BbnphaGwsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIGZpbGwgPSAndG96ZXJveScsY29sb3IgPSB+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iQW1vdW50IGJ5IEdlbnJlIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQojIyMgU3RhY2tlZCBMaW5lcyB7LmFjdGl2ZX0NCg0KYGBge3IgcGxvdChBbW91bnRPZkdhbWVzQnlHZW5yZWJ5WWVhcjMpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoQW56YWhsID1uKCkpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsQW56YWhsKQ0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW56YWhsIg0KDQopDQoNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5BbnphaGwsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIHN0YWNrZ3JvdXAgPSAnb25lJyxjb2xvciA9IH5HZW5yZSwgY29sb3JzID0gbXlQYWxldHRlKSU+JSANCiAgbGF5b3V0KHRpdGxlPSJBbW91bnQgYnkgR2VucmUgZnJvbSAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQoNCiMjIyBHZW5yZXNoaWZ0ICUNCg0KYGBge3IgcGxvdChBbW91bnRPZkdhbWVzQnlHZW5yZWJ5WWVhcjQpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoQW56YWhsID1uKCkpICU+JSBmaWx0ZXIoWWVhciE9J04vQScpJT4lZmlsdGVyKFllYXIhPTIwMjApICU+JSBmaWx0ZXIoWWVhciE9JzIwMTcnKSAlPiUNCiAgYXMuZGF0YS5mcmFtZSgpDQoNCg0KZmlsdGVyZWQgPC0gZ3JvdXBlZCAlPiUgc2VsZWN0KFllYXIsR2VucmUsQW56YWhsKQ0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiUGVyY2VudCAlIg0KDQopDQoNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5BbnphaGwsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIHN0YWNrZ3JvdXAgPSAnb25lJyxncm91cG5vcm0gPSAncGVyY2VudCcsY29sb3IgPSB+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iTWFya2V0YW1vdW50IGdlbnJlc2hpZnQgaW4gJSBmcm9tIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIHstfQ0KDQpIaWVyYmVpIHp1IGVya2VubmVuIGlzdCBPYndvaGwgZGllIEFuemFobCBkZXIgSsOkaHJsaWNoZW4gU3BpZWxlcmVsZWFzZXMgw7xiZXIgZGllIEphaHJlIGhpbndlZyBzdGV0aWcgd8OkY2hzdCBibGVpYmVuIGRpZSBNZWlzdGVuIEdlbnJlcyDDpGhubGljaCB2aWVsIHZlcnRyZXRlbi4gQXVmZsOkbGxpZyBzaW5kIGhpZXJiZWkgU3RyYXRlZ3ktR2FtZXMgZGllIGVyc3QgMTk5MSBkYXMgZXJzdGUgbWFsIGF1ZnRyZXRlbSBTZWl0ZGVtIG9id29obCBzaWUgTGVpY2h0IGFuIE1hcmtldHNoYXJlIHZlcmxpZXJlbiBncm9iIGdsZWljaCBibGVpYmVuLiBBdcOfZXJkZW0gc2luZCBBY3Rpb24gR2FtZXMgZGllIFNwaWVsZSBtaXQgZGVyIHdvaGwgZ3LDtsOfdGVuIHZvbGF0aWxpdMOkdC4gU2luZCBlcyAxOTgyIG5vY2ggZmFzdCA1MCUgZGVyIEdhbWVyZWxlYXNlcyBmw6RsbHQgZGVyZW4gYXVma29tbWVuIDEwODQgc2Nob24gYXVmIG51ciBub2NoIGtuYXBwIDEwJSBhYiB1bmQgMTk4NiBzdGVpZ3QgZGVyIFdlcnQgd2llZGVyIGF1ZiBmYXN0IDMwJS4gRGllc2VyIFRyZW5kIHNldHp0IHNpY2ggZm9ydCBiaXMgMTk5NiBhYiB3ZWxjaGVtIFplaXRwdW5rdCBzaWNoIEFjdGlvbiBHYW1lcyB2b24gMy42JSDDvGJlciBkaWUgSmFocmUgYmlzIDIwMTYgYmlzIDM1JSBlbnR3aWNrZWxuLg0KDQpTY2hhdWVuIHdpciB1bnMgYW4gd2llIHNpY2ggZGllIHZlcmvDpHVmZSBlbnR3aWNrZWx0IGhhYmVuLg0KDQojIyBTYWxlcyBBbW91bnQgcGVyIFllYXIgey50YWJzZXR9DQoNCiMjIyBMaW5lcw0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVieVllYXIxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLGdyX3N1bSkNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2xvYmFsX1NhbGVzIg0KDQopDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSgpICU+JSANCiAgYWRkX2xpbmVzKHg9flllYXIsDQogICAgICAgICAgIHk9fmdyX3N1bSwgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBieSBHZW5yZSBmcm9tIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANCiMjIyBGaWxsZWQgTGluZXMNCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVieVllYXIyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLGdyX3N1bSkNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2xvYmFsX1NhbGVzIg0KDQopDQoNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5ncl9zdW0sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIGZpbGwgPSAndG96ZXJveScsY29sb3IgPSB+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KDQojIyMgU3RhY2tlZCBMaW5lcyB7LmFjdGl2ZX0NCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVieVllYXIzKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLGdyX3N1bSkNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2xvYmFsX1NhbGVzIg0KDQopDQoNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5ncl9zdW0sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIHN0YWNrZ3JvdXAgPSAnb25lJyxjb2xvciA9IH5HZW5yZSAsY29sb3JzID0gbXlQYWxldHRlKSU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBieSBHZW5yZSBmcm9tIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KYGBgDQoNCiMjIyBHZW5yZXNoaWZ0ICUNCg0KYGBge3IgcGxvdChTYWxlc0J5R2VucmVieVllYXI0KSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLGdyX3N1bSkNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiWWVhciINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiUGVyY2VudCAlIg0KDQopDQoNCg0KZmlsdGVyZWQgJT4lDQpwbG90X2x5KHggPSB+WWVhciwgeSA9IH5ncl9zdW0sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbm9uZScsIHN0YWNrZ3JvdXAgPSAnb25lJyxncm91cG5vcm0gPSAncGVyY2VudCcsY29sb3IgPSB+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iTWFya2V0c2hhcmUgZ2VucmVzaGlmdCBpbiAlIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KIyMgey19DQoNCldpZSB6dSBlcndhcnRlbiBsw6Rzc3Qgc2ljaCBoaWVyIGVpbiBHcm/Dn2VyIG92ZXJsYXAgenUgZGVuIEFuemFobCBkZXIgR2FtZXJlbGVhc2VzIGZlc3RzdGVsbGVuLg0KDQpOdW4gc3RlbGx0IHNpY2ggZGllIEZyYWdlIGhhYiBzaWNoIGRpZSBWZXJrw6R1ZmUgw6RobmxpY2ggZGVyIGFuemFobCBkZXIgR2FtZVJlbGVhc2VzIGVudHdpY2tlbHQ/DQoNCiMjIFNhbGVzIHBlciBHYW1lIHBlciBZZWFyIHsudGFic2V0fQ0KDQojIyMgTGluZXMNCmBgYHtyIHBsb3QoU2FsZXNQZXJHYW1lUGVyR2VucmVieVllYXIxKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpL24oKSkgJT4lIGZpbHRlcihZZWFyIT0nTi9BJyklPiVmaWx0ZXIoWWVhciE9MjAyMCkgJT4lIGZpbHRlcihZZWFyIT0nMjAxNycpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KDQpmaWx0ZXJlZCA8LSBncm91cGVkICU+JSBzZWxlY3QoWWVhcixHZW5yZSxncl9zdW0pDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJZZWFyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyBwZXIgR2FtZSINCg0KKQ0KDQpmaWx0ZXJlZCAlPiUNCnBsb3RfbHkoKSAlPiUgDQogIGFkZF9saW5lcyh4PX5ZZWFyLA0KICAgICAgICAgICB5PX5ncl9zdW0sIGNvbG9yPX5HZW5yZSAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgcGVyIEdhbWUgYnkgR2VucmUgZnJvbSAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQoNCiMjIyBGaWxsZWQgTGluZXMNCg0KYGBge3IgcGxvdChTYWxlc1BlckdhbWVQZXJHZW5yZWJ5WWVhcjIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykvbigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLGdyX3N1bSkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlllYXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIHBlciBHYW1lIg0KDQopDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+Z3Jfc3VtLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBmaWxsID0gJ3RvemVyb3knLGNvbG9yID0gfkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBwZXIgR2FtZSBieSBHZW5yZSBmcm9tIDE5ODAtMjAxNiIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheQ0KICAgICAgICAgKQ0KDQpgYGANCg0KIyMjIFN0YWNrZWQgTGluZXMgey5hY3RpdmV9DQoNCmBgYHtyIHBsb3QoU2FsZXNQZXJHYW1lUGVyR2VucmVieVllYXIzKSxlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICBncm91cF9ieShZZWFyLCBHZW5yZSkgJT4lDQogIGRwbHlyOjpzdW1tYXJpemUoZ3Jfc3VtID0gc3VtKEdsb2JhbF9TYWxlcykvbigpKSAlPiUgZmlsdGVyKFllYXIhPSdOL0EnKSU+JWZpbHRlcihZZWFyIT0yMDIwKSAlPiUgZmlsdGVyKFllYXIhPScyMDE3JykgJT4lDQogIGFzLmRhdGEuZnJhbWUoKQ0KDQoNCmZpbHRlcmVkIDwtIGdyb3VwZWQgJT4lIHNlbGVjdChZZWFyLEdlbnJlLGdyX3N1bSkNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIlllYXIiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIHBlciBHYW1lIg0KDQopDQoNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+Z3Jfc3VtLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBzdGFja2dyb3VwID0gJ29uZScsY29sb3IgPSB+R2VucmUsIGNvbG9ycyA9IG15UGFsZXR0ZSklPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgcGVyIEdhbWUgYnkgR2VucmUgZnJvbSAxOTgwLTIwMTYiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCmBgYA0KDQojIyMgR2VucmVzaGlmdCAlDQoNCmBgYHtyIHBsb3QoU2FsZXNQZXJHYW1lUGVyR2VucmVieVllYXI0KSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgZ3JvdXBfYnkoWWVhciwgR2VucmUpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGdyX3N1bSA9IHN1bShHbG9iYWxfU2FsZXMpL24oKSkgJT4lIGZpbHRlcihZZWFyIT0nTi9BJyklPiVmaWx0ZXIoWWVhciE9MjAyMCkgJT4lIGZpbHRlcihZZWFyIT0nMjAxNycpICU+JQ0KICBhcy5kYXRhLmZyYW1lKCkNCg0KDQpmaWx0ZXJlZCA8LSBncm91cGVkICU+JSBzZWxlY3QoWWVhcixHZW5yZSxncl9zdW0pDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJZZWFyIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJQZXJjZW50ICUiDQoNCikNCmZpbHRlcmVkICU+JQ0KcGxvdF9seSh4ID0gflllYXIsIHkgPSB+Z3Jfc3VtLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ25vbmUnLCBzdGFja2dyb3VwID0gJ29uZScsZ3JvdXBub3JtID0gJ3BlcmNlbnQnLGNvbG9yID0gfkdlbnJlLCBjb2xvcnMgPSBteVBhbGV0dGUpJT4lIA0KICBsYXlvdXQodGl0bGU9Ik1hcmtldHNoYXJlIGluIFNhbGVzIHBlciBHYW1lIGJ5IEdlbnJlIGZyb20gMTk4MC0yMDE2IiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQpgYGANCg0KIyMgey19DQpBdWNoIGhpZXIgaXN0IHdpZSBlcndhcnRldCBkaWUgRW50d2lja2x1bmcgUHJvemVudHVhbCDDpGhubGljaCBzaW5kLiBBdWZmw6RsbGlnIGlzdCBqZWRvY2ggZGFzIFNob290ZXIgdHJvdHogaWhyZXIgZ2VyaW5nZW4gVmVydHJldHVuZyBpbiBkZXIgUHJvemVudHVhbGVuIFZlcnRlaWx1bmcgMTk4NCBzb3dpZSAyMDE0LDIwMTUgdW5kIDIwMTYgZGllIE5hc2UgVm9ybmUgaGFiZW4uIFBsYXRmb3JtIEdhbWVzIGhhYmVuIDE5ODUsMTk4OCB1bmQgMTk5MCBkaWUgTmFzZSBWb3JuZS4gRGllIEhvY2h6ZWl0IGRlciBQdXp6bGUgR2FtZXMgc2luZCB1bmFuZ2Vmb2NodGVuIDE5ODggbWl0IGRlbSBXZWx0d2VpdGJla2FubnRlbiB1bmQgYXVmIFBsYXR6IDYgZGVyIG1laXN0dmVya2F1ZnRlbiB2aWRlb3NwaWVsZTogVGV0cmlzLiBFaW4gZ2VuYXVlcmVyIHZlcmdsZWljaCBkZXIgQXVzc2NobMOkZ2UgbWl0IGRlbiBkZW1lbnRzcHJlY2hlbmRlbiBWaWRlb3NwaWVsZW4gd8OkcmUgaGllciB3w7xuc2NoZW5zd2VydCB3w7xyZGUgYWJlciBkYXMgQXVzbWHDnyBkaWVzZXIgQXJiZWl0IHNwcmVuZ2VuLg0KDQoNCk51biBzdGVsbHQgc2ljaCBkaWUgRnJhZ2Ugd2llIGVzIG1pdCBHZW5yZXMgcHJvIHB1Ymxpc2hlciBhdXNzaWVodD8gR2lidCBlcyBoaWVyIFB1Ymxpc2hlciBkaWUgdmVyc2NoaWVkZW5lIEdlbnJlcyBiZXZvcnp1Z2VuIGJ6dy4gZGVyZW4gQmVzdHNlbGxlciBzaWNoIGluIGJlc3RpbW10ZW4gR2VucmVzIFR1bW1lbG4/DQoNCkhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIGVpbiBzdGFja2VkIEJhci1QbG90LiBEYXp1IGZpbHRlcm4gd2lyIGRpZSB0b3AgMTAgUHVibGlzaGVybiBha2EgUHVibGlzaGVyIG1pdCBtaW4gMTE2IG1pbyBpbiBTYWxlcy4gRGllcyBlbnRmZXJudCBuYXTDvHJsaWNoIGVpbmlnZXMgYW4gSW5mb3JtYXRpb24gYWxsZXJkaW5ncyBnZWh0IHNvbnN0IGVpbmlnZXMgYW4gw5xiZXJzaWNodGxpY2hrZWl0IHZlcmxvcmVuLiBadXPDpHR6bGljaCB3ZXJkZW4gZXJuZXV0IGRpZSBXb3J0ZSAiRW50ZXJ0YWlubWVudCIsICJJbnRlcmFjdGl2ZSIsICJHYW1lIiwgIkdhbWVzIiB1bmQgIlN0dWRpb3MiIGVudGZlcm50Lg0KDQojIyBHZW5yZSBieSBQdWJsaXNoZXIgey50YWJzZXR9DQoNCiMjIyBTYWxlcw0KDQpgYGB7ciBwbG90KFNhbGVzR2VucmVieVB1Ymxpc2hlciksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcixHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSANCg0KUHVibGlzaGVyU2FsZXMgPC0gZ3JvdXBlZCAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KZ3JvdXBlZCA8LSBncm91cGVkICU+JSBmaWx0ZXIoUHVibGlzaGVyICVpbiUgUHVibGlzaGVyU2FsZXMkUHVibGlzaGVyKQ0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0KDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0KZ3JvdXBlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChncm91cGVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0KZ3JvdXBlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChncm91cGVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCmdyb3VwZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwoZ3JvdXBlZCRQdWJsaXNoZXIsICJHYW1lIikNCg0KICANCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIg0KDQopDQoNCmdyb3VwZWQlPiUNCiAgcGxvdF9seSh4PX5QdWJsaXNoZXIsDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgIHR5cGU9J2JhcicsDQogICAgICAgICAgIGNvbG9yPX5HZW5yZSwgY29sb3JzID0gbXlQYWxldHRlKSAgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIEJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheSwNCiAgICAgICAgIGJhcm1vZGUgPSAnc3RhY2snDQogICAgICAgICApDQoNCg0KYGBgDQoNCiMjIyBBbW91bnQNCg0KYGBge3IgcGxvdChBbW91bnRHZW5yZWJ5UHVibGlzaGVyKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KDQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIsR2VucmUpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpLHN1bShHbG9iYWxfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkNCg0KUHVibGlzaGVyU2FsZXMgPC0gZ3JvdXBlZCAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcikgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSBmaWx0ZXIoR2xvYmFsX1NhbGVzPjMwMCkNCg0KDQoNCmdyb3VwZWQgPC0gZ3JvdXBlZCAgJT4lIGZpbHRlcihQdWJsaXNoZXIgJWluJSBQdWJsaXNoZXJTYWxlcyRQdWJsaXNoZXIpDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiRW50ZXJ0YWlubWVudCIpDQpncm91cGVkJFB1Ymxpc2hlciA8LXN0cl9yZW1vdmVfYWxsKGdyb3VwZWQkUHVibGlzaGVyLCAiSW50ZXJhY3RpdmUiKQ0KZ3JvdXBlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChncm91cGVkJFB1Ymxpc2hlciwgIlN0dWRpb3MiKQ0KZ3JvdXBlZCRQdWJsaXNoZXIgPC1zdHJfcmVtb3ZlX2FsbChncm91cGVkJFB1Ymxpc2hlciwgIkdhbWVzIikNCmdyb3VwZWQkUHVibGlzaGVyIDwtc3RyX3JlbW92ZV9hbGwoZ3JvdXBlZCRQdWJsaXNoZXIsICJHYW1lIikNCg0KDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJBbW91bnQiDQoNCikNCg0KZ3JvdXBlZCU+JQ0KICBwbG90X2x5KHg9flB1Ymxpc2hlciwNCiAgICAgICAgICAgeT1+QW56YWhsLA0KICAgICAgICAgICAgdHlwZT0nYmFyJywNCiAgICAgICAgICAgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICAlPiUgDQogIGxheW91dCh0aXRsZT0iQW1vdW50IGJ5IEdlbnJlIEJ5IFB1Ymxpc2hlciIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheSwNCiAgICAgICAgIGJhcm1vZGUgPSAnc3RhY2snDQogICAgICAgICApDQoNCg0KDQpgYGANCg0KIyMgey19DQoNCkJlaSBkZW0gdmVyZ2xlaWNoIGRlciBXZXJ0ZSBpc3QgaGllciB6dSBiZW1lcmtlbiwgZGFzcyBkaWUgbWVpc3RlbiBQdWJsaXNoZXIgSGllcmJlaSBzaWNoIG1pdCBkZXIgQW56YWhsIGRlciBTcGllbGUgdW5kIGRlbiBTYWxlcyBndXQgYWJkZWNrZW4uIERpZSBhdWZmw6RsbGlnc3RlbiBkaXNrcmVwYW56ZW4gc2luZCBoaWVyYmVpIEVBIG1pdCBkZW0gU3BvcnRzIEdlbnJlIHVuZCBpaHJlbiBqw6RybGljaCByZWxlYXN0ZW4gU3BpZWxlbiBGaUZhL05CQTJrIGV0Yy4gc293aWUgTmludGVuZG8gbWl0IGRlciBQbGF0Zm9ybXJlaWhlIFN1cGVyIE1hcmlvLiBTY2hhdWVuIHdpciB1bnMgZGllc2UgQmVpZGVuIEZpcm1lbiBOb2NoIGVpbm1hbCBpbSBEZXRhaWwgYW4uDQoNCkhpZXJ6dSB2ZXJ3ZW5kZW4gd2lyIHdpZWRlciBkaWUgQmFyL1BpZSBjaGFydCBDb21ibyBkaWUgdW5zIEJlcmVpdHMgYXVzIHZvcmRlcmVuIFRlaWxlbiBkZXIgQXVzYXJiZWl0dW5nIGJla2FubnQgc2luZC4NCg0KIyMgR2VucmUgZsO8ciBFbGVjdHJvbmljIEFydHMgey50YWJzZXR9DQoNCiMjIyBCYWxrZW5kaWFncmFtbWUgey50YWJzZXR9DQoNCiMjIyMgU2FsZXMgDQoNCmBgYHtyIHBsb3QoR2VucmVieVB1Ymxpc2hlckVBMSksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcixHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoc3VtKEdsb2JhbF9TYWxlcykpICAlPiUNCnJlbmFtZSgNCiAgICBHbG9iYWxfU2FsZXMgPSAic3VtKEdsb2JhbF9TYWxlcykiDQogICAgKSAlPiUgDQogIGZpbHRlcihQdWJsaXNoZXIgPT0gIkVsZWN0cm9uaWMgQXJ0cyIpDQoNCg0KZ3JvdXBlZCRHbG9iYWxfU2FsZXM8LWFzX3ZlY3Rvcihncm91cGVkJEdsb2JhbF9TYWxlcykNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIlNhbGVzIg0KDQopDQoNCmdyb3VwZWQlPiUNCiAgcGxvdF9seSgpICU+JSBhZGRfYmFycyh4PX5HZW5yZSwNCiAgICAgICAgICAgeT1+R2xvYmFsX1NhbGVzLA0KICAgICAgICAgICBjb2xvcj1+R2VucmUgLGNvbG9ycyA9IG15UGFsZXR0ZSkgICU+JSANCiAgbGF5b3V0KHRpdGxlPSJTYWxlcyBieSBHZW5yZSBmb3IgRWxlY3Ryb25pYyBBcnRzIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5LA0KICAgICAgICAgYmFybW9kZSA9ICdzdGFjaycNCiAgICAgICAgICkNCg0KYGBgDQojIyMjIEFtb3VudA0KDQpgYGB7ciBwbG90KEFtb3VudEdlbnJlYnlQdWJsaXNoZXJFQTEpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSkgICU+JSANCiAgZmlsdGVyKFB1Ymxpc2hlciA9PSAiRWxlY3Ryb25pYyBBcnRzIikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW1vdW50Ig0KDQopDQoNCg0KZ3JvdXBlZCU+JQ0KICBwbG90X2x5KCkgJT4lIGFkZF9iYXJzKHg9fkdlbnJlLA0KICAgICAgICAgICB5PX5BbnphaGwsDQogICAgICAgICAgIGNvbG9yPX5HZW5yZSAsY29sb3JzID0gbXlQYWxldHRlKSAgJT4lIA0KICBsYXlvdXQodGl0bGU9IkFtb3VudCBieSBHZW5yZSBmb3IgRWxlY3Ryb25pYyBBcnRzICIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheSwNCiAgICAgICAgIGJhcm1vZGUgPSAnc3RhY2snDQogICAgICAgICApDQoNCmBgYA0KIyMjIEtyZWlzZGlhZ3JhbW1lIHsudGFic2V0fQ0KDQojIyMjIFNhbGVzIA0KDQpgYGB7ciBwbG90KEdlbnJlYnlQdWJsaXNoZXJFQTIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIsR2VucmUpICU+JSANCiAgc3VtbWFyaXplKHN1bShHbG9iYWxfU2FsZXMpKSAgJT4lDQpyZW5hbWUoDQogICAgR2xvYmFsX1NhbGVzID0gInN1bShHbG9iYWxfU2FsZXMpIg0KICAgICkgJT4lIA0KICBmaWx0ZXIoUHVibGlzaGVyID09ICJFbGVjdHJvbmljIEFydHMiKQ0KDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyINCg0KKQ0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+R2VucmUsdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnLHNvcnQgPSBGQUxTRSwNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgYnkgR2VucmUgZm9yIEVsZWN0cm9uaWMgQXJ0cyIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IlNhbGVzIGJ5IEdlbnJlIGZvciBFbGVjdHJvbmljIEFydHMiLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KDQpgYGANCg0KDQojIyMjIEFtb3VudA0KDQpgYGB7ciBwbG90KEFtb3VudEdlbnJlYnlQdWJsaXNoZXJFQTIpLCBlY2hvID0gVFJVRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0nbWFya3VwJywgfQ0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShBbnphaGwgPW4oKSkgICU+JSANCiAgZmlsdGVyKFB1Ymxpc2hlciA9PSAiRWxlY3Ryb25pYyBBcnRzIikNCg0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW1vdW50Ig0KDQopDQoNCmdyb3VwZWQlPiUNCiAgcGxvdF9seSgpICU+JSANCiAgYWRkX3BpZSh2YWx1ZXMgPX5BbnphaGwsbGFiZWxzPX5HZW5yZSx0ZXh0aW5mbz0nbGFiZWwrcGVyY2VudCcsc29ydCA9IEZBTFNFLA0KICAgICAgICAgICBuYW1lPSJBbW91bnQgYnkgR2VucmUgZm9yIEVsZWN0cm9uaWMgQXJ0cyIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkFtb3VudCBieSBHZW5yZSBmb3IgRWxlY3Ryb25pYyBBcnRzIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCmBgYA0KIyMgey19DQpTY2hhdWVuIHdpciB1bnMgRUEgaGllciBpbSBEZXRhaWwgYW4gZsOkbGx0IGFsbGVyZGluZ3MgYXVmIGRhcyBkaWUgRGlza3JlcGFueiB6d2lzY2hlbiBTYWxlcyB1bmQgQW56YWhsIGRlciBHYW1lcmVsZWFzZXMgZsO8ciBFQSBiZWkgU3BvcnRzIGdhciBuaWNodCBzbyBncm/DnyBpc3QgKDQxLjUlIHZzIDQzLjIlKS4gRGllIGdyw7bDn2VyZW4gZGlza3JlcGFuemVuIHNpbmQgaGllciBTaG9vdGVyIHdlbGNoZXMgbnVyIDEwJSBkZXIgR2FtZXJlbGVhc2VzIHNpbmQgYWJlciBndXQgMTUlIGRlciBTYWxlcyB1bmQgQWN0aW9uIG1pdCAxMy41JSBkZXIgR2FtZXJlbGVhc2VzIHVuZCAxMC40JSBkZXIgU2FsZXMuDQoNClNjaGF1ZW4gd2lyIHVucyBudW4gTmludGVuZG8gYW4uDQoNCiMjIEdlbnJlIGbDvHIgTmludGVuZG8gey50YWJzZXR9DQoNCiMjIyBCYWxrZW5kaWFncmFtbWUgey50YWJzZXR9DQoNCiMjIyMgU2FsZXMNCg0KYGBge3IgcGxvdChHZW5yZWJ5UHVibGlzaGVyTmludGVuZG8xKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSANCiAgZmlsdGVyKFB1Ymxpc2hlciA9PSAiTmludGVuZG8iKQ0KDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyINCg0KKQ0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgYWRkX2JhcnMoeD1+R2VucmUsDQogICAgICAgICAgIHk9fkdsb2JhbF9TYWxlcywNCiAgICAgICAgICAgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgYnkgR2VucmUgZm9yIE5pbnRlbmRvIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5LA0KICAgICAgICAgYmFybW9kZSA9ICdzdGFjaycNCiAgICAgICAgICkNCg0KDQpgYGANCg0KDQojIyMjIEFtb3VudA0KYGBge3IgcGxvdChBbW91bnRHZW5yZWJ5UHVibGlzaGVyTmludGVuZG8xKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KZ3JvdXBlZCA8LSB2Z3NhbGVzICAlPiUgDQogIGdyb3VwX2J5KFB1Ymxpc2hlcixHZW5yZSkgJT4lIA0KICBzdW1tYXJpemUoQW56YWhsID1uKCkpICAlPiUgDQogIGZpbHRlcihQdWJsaXNoZXIgPT0gIk5pbnRlbmRvIikNCg0KDQpncm91cGVkJEdsb2JhbF9TYWxlczwtYXNfdmVjdG9yKGdyb3VwZWQkR2xvYmFsX1NhbGVzKQ0KDQpheCA8LSBsaXN0KA0KICB0aXRsZSA9ICJHZW5yZSINCikNCg0KYXkgPC0gbGlzdCgNCiAgdGl0bGUgPSAiQW1vdW50Ig0KDQopDQoNCg0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgYWRkX2JhcnMoeD1+R2VucmUsDQogICAgICAgICAgIHk9fkFuemFobCwNCiAgICAgICAgICAgY29sb3I9fkdlbnJlICxjb2xvcnMgPSBteVBhbGV0dGUpICAlPiUgDQogIGxheW91dCh0aXRsZT0iQW1vdW50IGJ5IEdlbnJlIGZvciBOaW50ZW5kbyIsDQogICAgICAgICB4YXhpcyA9IGF4LA0KICAgICAgICAgeWF4aXMgPSBheSwNCiAgICAgICAgIGJhcm1vZGUgPSAnc3RhY2snDQogICAgICAgICApDQoNCmBgYA0KDQojIyMgS3JlaXNkaWFncmFtbWUgey50YWJzZXR9DQoNCiMjIyMgU2FsZXMNCg0KYGBge3IgcGxvdChHZW5yZWJ5UHVibGlzaGVyTmludGVuZG8yKSwgZWNobyA9IFRSVUUsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIH0NCg0KDQpncm91cGVkIDwtIHZnc2FsZXMgICU+JSANCiAgZ3JvdXBfYnkoUHVibGlzaGVyLEdlbnJlKSAlPiUgDQogIHN1bW1hcml6ZShzdW0oR2xvYmFsX1NhbGVzKSkgICU+JQ0KcmVuYW1lKA0KICAgIEdsb2JhbF9TYWxlcyA9ICJzdW0oR2xvYmFsX1NhbGVzKSINCiAgICApICU+JSANCiAgZmlsdGVyKFB1Ymxpc2hlciA9PSAiTmludGVuZG8iKQ0KDQoNCmdyb3VwZWQkR2xvYmFsX1NhbGVzPC1hc192ZWN0b3IoZ3JvdXBlZCRHbG9iYWxfU2FsZXMpDQoNCmF4IDwtIGxpc3QoDQogIHRpdGxlID0gIkdlbnJlIg0KKQ0KDQpheSA8LSBsaXN0KA0KICB0aXRsZSA9ICJTYWxlcyINCg0KKQ0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+R2xvYmFsX1NhbGVzLGxhYmVscz1+R2VucmUsdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnLHNvcnQgPSBGQUxTRSwNCiAgICAgICAgICAgbmFtZT0iU2FsZXMgYnkgR2VucmUgZm9yIE5pbnRlbmRvIiAsY29sb3JzID0gbXlQYWxldHRlKSAlPiUgDQogIGxheW91dCh0aXRsZT0iU2FsZXMgYnkgR2VucmUgZm9yIE5pbnRlbmRvIiwNCiAgICAgICAgIHhheGlzID0gYXgsDQogICAgICAgICB5YXhpcyA9IGF5DQogICAgICAgICApDQoNCg0KYGBgDQoNCiMjIyMgQW1vdW50DQoNCmBgYHtyIHBsb3QoQW1vdW50R2VucmVieVB1Ymxpc2hlck5pbnRlbmRvMiksIGVjaG8gPSBUUlVFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdtYXJrdXAnLCB9DQoNCmdyb3VwZWQgPC0gdmdzYWxlcyAgJT4lIA0KICBncm91cF9ieShQdWJsaXNoZXIsR2VucmUpICU+JSANCiAgc3VtbWFyaXplKEFuemFobCA9bigpKSAgJT4lIA0KICBmaWx0ZXIoUHVibGlzaGVyID09ICJOaW50ZW5kbyIpDQoNCg0KYXggPC0gbGlzdCgNCiAgdGl0bGUgPSAiR2VucmUiDQopDQoNCmF5IDwtIGxpc3QoDQogIHRpdGxlID0gIkFtb3VudCINCg0KKQ0KDQpncm91cGVkJT4lDQogIHBsb3RfbHkoKSAlPiUgDQogIGFkZF9waWUodmFsdWVzID1+QW56YWhsLGxhYmVscz1+R2VucmUsdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnLHNvcnQgPSBGQUxTRSwNCiAgICAgICAgICAgbmFtZT0iQW1vdW50IGJ5IEdlbnJlIGZvciBOaW50ZW5kbyIgLGNvbG9ycyA9IG15UGFsZXR0ZSkgJT4lIA0KICBsYXlvdXQodGl0bGU9IkFtb3VudCBieSBHZW5yZSBmb3IgTmludGVuZG8iLA0KICAgICAgICAgeGF4aXMgPSBheCwNCiAgICAgICAgIHlheGlzID0gYXkNCiAgICAgICAgICkNCg0KYGBgDQoNCiMjIHstfQ0KDQpCZWkgTmludGVuZG8genUgZXJrZW5uZW4gaXN0IGhpZXIsIGRhc3MgUGxhdGZvcm0gc3BpZWxlIGVpbiBLYXNzZW5jaGxhZ2VyIHNpbmQuIE5laG1lbiBkaWVzZSBudXIgMTYlIGRlciBzcGllbGVyZWxlYXNlcyBlaW4gc28gYnJpbmdlbiBzaWUgZGVubm9jaCAyNCUgZGVyIFNhbGVzIGVpbi4gR2xlaWNoZXMgR2lsdCBmw7xyIFNwb3J0IGdhbWVzLiA4JSBnZWdlbsO8YmVyIDEyJS4gQWN0aW9uICgxMSUgdnMgNyUpLCBNaXNjICgxNCUgdnMgMTAlKSB1bmQgUHV6emxlIEdhbWVzICgxMC41JSB2cyA3JSkgc2luZCBqZWRvY2ggbmljaHQgc28gZXJmb2xncmVpY2guDQoNCg0KIyBBdXNibGljayBpbiBkaWUgWnVrdW5mdA0KDQpFaW4gVmVyZ2xlaWNoIGRlciBBdXNzY2hsw6RnZSBtaXQgZGVuIGRlbWVudHNwcmVjaGVuZGVuIFZpZGVvc3BpZWxlbi4NCg0KRWluZSBnZW5hdWUgQW5hbHlzZSBkZXIgR2FtZXNhbGVzIHBybyBqYWhyIChha2EgdGV0cmlzdCAxOTUwIDMwIG1hbCB0ZXN0cmlzIDIwMTUgMzAwMDAwIG1hbCkgZ2ViZW4gZGllIGRhdGVuIG5pY2h0IGhlci4NCg0KZWluZSBhbnlsc2UgZGVyIENvcm9uYXBhbmRlbWllIHZlcsOkbmRlcnVuZ2VuIChnZWJlbiBkaWUgZGF0ZW4gbmljaHQgaGVyKQ0K